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

3 回答 3

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

    }
}

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

于 2017-09-03T12:36:10.473 回答
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
}
于 2018-11-10T18:31:47.307 回答
0

在阅读您的功能时,我问自己两件事。

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

  2. 感觉就像您正在创建的 newContact 正在丢失大量信息。喜欢昵称或前缀(医生等)。

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

于 2019-08-20T22:06:58.650 回答