合并重复的CNCONTACT数组-使用Swift 3联系人框架。

3

我通过这种方法找到了重复的联系人列表,现在我卡在了合并重复项上,你有什么想法吗?

我使用了从之前问题中引用的代码来获取重复项。

let formatter = CNContactFormatter()
formatter.style = .fullName

let keys = [CNContactIdentifierKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)]
let request = CNContactFetchRequest(keysToFetch: keys)
var contactsByName = [String: [CNContact]]()
try! self.store.enumerateContacts(with: request) { contact, stop in
    guard let name = formatter.string(from: contact) else { return }
    contactsByName[name] = (contactsByName[name] ?? []) + [contact]   // or in Swift 4, `contactsByName[name, default: []].append(contact)`
}
let duplicates = contactsByName.filter { $1.count > 1 }
3个回答

0

在阅读您的函数时,我有两个问题。

  1. newContact.phoneNumbers:看起来您将来自2个联系人的所有号码都添加到了一起。如果这2个重复的联系人具有相同的号码,则新联系人的列表中将会有两个相同的号码,对吗?

  2. 感觉您正在创建的新联系人丢失了很多信息。例如昵称或前缀(医生等...)。

无论如何,感谢您提供这个简洁的代码 :)


0
如果您按照我之前的答案获取了重复列表,那么您可以使用此代码来合并重复项。
func mergeAllDuplicates() -> CNContact {

    let duplicates: [Array<CNContact>] = //Array of Duplicates Contacts

    for item in duplicates {

        // CNCONTACT PROPERTIES

        var namePrefix: [String] = [String]()
        var givenName: [String] = [String]()
        var middleName: [String] = [String]()
        var familyName: [String] = [String]()
        var previousFamilyName: [String] = [String]()
        var nameSuffix: [String] = [String]()
        var nickname: [String] = [String]()
        var organizationName: [String] = [String]()
        var departmentName: [String] = [String]()
        var jobTitle: [String] = [String]()
        var phoneNumbers: [CNPhoneNumber] = [CNPhoneNumber]()
        var emailAddresses: [NSString] = [NSString]()
        var postalAddresses: [CNPostalAddress] = [CNPostalAddress]()
        var urlAddresses: [NSString] = [NSString]()

        var contactRelations: [CNContactRelation] = [CNContactRelation]()
        var socialProfiles: [CNSocialProfile] = [CNSocialProfile]()
        var instantMessageAddresses: [CNInstantMessageAddress] = [CNInstantMessageAddress]()

        // Filter
        for items in item {
            namePrefix.append(items.namePrefix)
            givenName.append(items.givenName)
            middleName.append(items.middleName)
            familyName.append(items.familyName)
            previousFamilyName.append(items.previousFamilyName)
            nameSuffix.append(items.nameSuffix)
            nickname.append(items.nickname)
            organizationName.append(items.organizationName)
            departmentName.append(items.departmentName)
            jobTitle.append(items.jobTitle)

            for number in items.phoneNumbers {
                phoneNumbers.append(number.value)
            }
            for email in items.emailAddresses {
                emailAddresses.append(email.value)
            }
            for postal in items.postalAddresses {
                postalAddresses.append(postal.value)
            }
            for url in items.urlAddresses {
                urlAddresses.append(url.value)
            }
            for relation in items.contactRelations {
                contactRelations.append(relation.value)
            }
            for social in items.socialProfiles {
                socialProfiles.append(social.value)
            }
            for message in items.instantMessageAddresses {
                instantMessageAddresses.append(message.value)
            }

        }

        let newContact = CNMutableContact()
        newContact.namePrefix = Array(Set(namePrefix))[0]
        newContact.givenName = Array(Set(givenName))[0]
        newContact.middleName = Array(Set(middleName))[0]
        newContact.familyName = Array(Set(familyName))[0]
        newContact.previousFamilyName = Array(Set(previousFamilyName))[0]
        newContact.nameSuffix = Array(Set(nameSuffix))[0]
        newContact.nickname = Array(Set(nickname))[0]
        newContact.organizationName = Array(Set(namePrefix))[0]
        newContact.departmentName = Array(Set(namePrefix))[0]
        newContact.jobTitle = Array(Set(namePrefix))[0]
        for item in Array(Set(phoneNumbers)) {
            newContact.phoneNumbers.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(emailAddresses)) {
            newContact.emailAddresses.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(postalAddresses)) {
            newContact.postalAddresses.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(urlAddresses)) {
            newContact.urlAddresses.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(contactRelations)) {
            newContact.contactRelations.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(socialProfiles)) {
            newContact.socialProfiles.append(CNLabeledValue(label: CNLabelHome, value: item))
        }
        for item in Array(Set(instantMessageAddresses)) {
            newContact.instantMessageAddresses.append(CNLabeledValue(label: CNLabelHome, value: item))
        }

        return newContact

    }
}

这种方法需要相当大的内存,因此我建议将其用作参考。

谢谢,我会尝试。 - user8541344
我试图在Stackoverflow上找到你的"获取重复列表的先前答案"。我找不到它。你能给我一个链接吗? - daniel

0

我稍微修改了一下。也许会有所帮助。

extension Array where Element == String {

    var bestElement: String? {
        var options: [String : Int] = [:]

        for element in self {
            if let result = options[element] {
                options[element] = result + 1
            } else {
                options[element] = 1
            }
        }

        return options.sorted { $0.1 > $1.1 }.first?.key
    }
}


static func merge(duplicates: [CNContact]) -> CNContact {
    // EMPTY CNCONTACT PROPERTIES
    var givenName: [String] = []
    var familyName: [String] = []
    var organizationName: [String] = []
    var notes: [String] = []

    var phoneNumbers: [CNLabeledValue<CNPhoneNumber>] = []
    var emailAddresses: [CNLabeledValue<NSString>] = []
    var postalAddresses: [CNLabeledValue<CNPostalAddress>] = []
    var urlAddresses: [CNLabeledValue<NSString>] = []

    // COLLECT VALUES
    for contact in duplicates {
        givenName.append(contact.givenName)
        familyName.append(contact.familyName)
        organizationName.append(contact.organizationName)
        notes.append(contact.note)

        contact.phoneNumbers.forEach { phoneNumbers.append($0) }
        contact.emailAddresses.forEach { emailAddresses.append($0) }
        contact.postalAddresses.forEach { postalAddresses.append($0) }
        contact.urlAddresses.forEach { urlAddresses.append($0) }
    }

    // MERGE TO NEW CONTACT
    let newContact = CNMutableContact()
    newContact.givenName = givenName.bestElement ?? ""
    newContact.familyName = familyName.bestElement ?? ""
    newContact.organizationName = organizationName.bestElement ?? ""
    newContact.note = notes.joined(separator: "\n")

    newContact.phoneNumbers = phoneNumbers
    newContact.emailAddresses = emailAddresses
    newContact.postalAddresses = postalAddresses
    newContact.urlAddresses = urlAddresses

    return newContact
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接