合并重复的 CNCONTACT 数组 swift 3 个联系人框架

Merge duplicate CNCONTACT array swift 3 contacts framework

我确实从这个方法中找到了重复的联系人列表,现在我被困在合并重复的列表中,不知道我该怎么做。

我使用引用自上一个问题的代码获取了副本。

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 { .count > 1 }

如果您在使用此代码合并重复项后按照我之前关于获取重复项列表的回答进行操作。

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

    }
}

这种方法会占用大量内存,所以我建议,使用这种方法作为参考。

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

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 { [=10=].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([=10=]) }
        contact.emailAddresses.forEach { emailAddresses.append([=10=]) }
        contact.postalAddresses.forEach { postalAddresses.append([=10=]) }
        contact.urlAddresses.forEach { urlAddresses.append([=10=]) }
    }

    // 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
}

我在阅读您的函数时问自己两件事。

  1. newContact.phoneNumbers:您似乎附加了 2 个联系人的所有号码。如果 2 个重复的联系人具有相同的号码,那么 newContact 将在其列表中两次具有相同的号码,对吗?

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

无论如何感谢这个紧凑的代码:)