You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击弹窗确定按钮后如何移除表格视图中的重复联系人?

Hey Fabio, let's tackle your two questions about handling duplicate contacts when tapping the OK button, and updating your Table View accordingly. First, let's finish and refine your findDuplicateContacts() method since it was cut off, then walk through each solution step by step.

1. Complete the findDuplicateContacts() Method

First, let's wrap up the logic to group contacts by name and identify duplicates. This will give us a clear list of contacts that need to be removed:

@objc fileprivate func findDuplicateContacts() -> [CNContact] {
    let keys = [
        CNContactIdentifierKey as CNKeyDescriptor,
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
    ]
    let request = CNContactFetchRequest(keysToFetch: keys)
    var contactsByName = [String: [CNContact]]()
    var duplicateContacts = [CNContact]()

    do {
        try self.contactStore.enumerateContacts(with: request) { contact, stop in
            guard let fullName = CNContactFormatter.string(from: contact, style: .fullName) else {
                return
            }
            // Group contacts by their full name
            contactsByName[fullName, default: []].append(contact)
        }

        // Extract duplicates (keep the first contact in each group, mark the rest for deletion)
        for (_, contacts) in contactsByName {
            if contacts.count > 1 {
                duplicateContacts.append(contentsOf: contacts.dropFirst())
            }
        }
    } catch {
        print("Error fetching contacts: \(error.localizedDescription)")
    }

    return duplicateContacts
}

This method now returns an array of duplicate contacts (all entries except the first occurrence of each named group).

2. Remove Duplicate Contacts When Tapping the OK Button

Next, add an action for your OK button. We'll use the CNContactStore to delete duplicates directly from the system contacts. Important: Ensure you've requested and been granted CNContactStoreAuthorizationType.fullAccess or writeOnly permissions first—users won't let you modify their contacts without explicit approval.

@IBAction func okButtonTapped(_ sender: UIButton) {
    let duplicates = findDuplicateContacts()
    guard !duplicates.isEmpty else {
        // No duplicates to remove, dismiss the popup
        self.dismiss(animated: true)
        return
    }

    // Optional: Add a user confirmation alert here to avoid accidental deletions
    let confirmAlert = UIAlertController(title: "Remove Duplicates?", message: "This will delete \(duplicates.count) duplicate contacts.", preferredStyle: .alert)
    confirmAlert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    confirmAlert.addAction(UIAlertAction(title: "Delete", style: .destructive) { [weak self] _ in
        self?.performDuplicateDeletion(duplicates: duplicates)
    })
    present(confirmAlert, animated: true)
}

private func performDuplicateDeletion(duplicates: [CNContact]) {
    let deleteRequest = CNSaveRequest()
    for contact in duplicates {
        guard let mutableContact = contact.mutableCopy() as? CNMutableContact else {
            continue
        }
        deleteRequest.delete(mutableContact)
    }

    // Execute the delete request
    do {
        try contactStore.execute(deleteRequest)
        print("Successfully removed \(duplicates.count) duplicate contacts")
        // Update the Table View and dismiss the popup
        updateTableViewAfterDeletion()
        self.dismiss(animated: true)
    } catch {
        print("Error deleting duplicates: \(error.localizedDescription)")
        // Show an error alert to the user
        let errorAlert = UIAlertController(title: "Error", message: "Failed to remove duplicates: \(error.localizedDescription)", preferredStyle: .alert)
        errorAlert.addAction(UIAlertAction(title: "OK", style: .default))
        present(errorAlert, animated: true)
    }
}
3. Update Table View to Remove Duplicate Entries

Assuming your Table View uses an array (e.g., var contacts: [CNContact] = []) as its data source, you'll need to sync it with the updated contact store. Here are two reliable ways to do this:

fileprivate func updateTableViewAfterDeletion() {
    // Option 1: Refetch fresh contacts from the store (most reliable, ensures up-to-date data)
    let keys = [
        CNContactIdentifierKey as CNKeyDescriptor,
        CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
    ]
    let request = CNContactFetchRequest(keysToFetch: keys)
    var freshContacts = [CNContact]()

    do {
        try contactStore.enumerateContacts(with: request) { contact, stop in
            freshContacts.append(contact)
        }
        // Update data source on main thread (UI updates must happen here)
        DispatchQueue.main.async {
            self.contacts = freshContacts
            self.tableView.reloadData()
        }
    } catch {
        print("Error refetching contacts: \(error.localizedDescription)")
    }

    // Option 2: Filter existing array (faster, if you trust your current data source is mostly up-to-date)
    // let duplicateIdentifiers = Set(findDuplicateContacts().map { $0.identifier })
    // DispatchQueue.main.async {
    //     self.contacts = self.contacts.filter { !duplicateIdentifiers.contains($0.identifier) }
    //     self.tableView.reloadData()
    // }
}

Option 1 is preferred because it pulls the latest state directly from the contact store, avoiding any inconsistencies between your local array and the system data.

Quick Notes:

  • Always handle permission checks: Before attempting to modify contacts, verify your app has the right authorization using contactStore.authorizationStatus(for: .contacts) and request it if needed.
  • Soft deletions: If you're worried about accidental data loss, you could first move duplicates to the user's "Recently Deleted" folder instead of permanent deletion (use deleteRequest.add(mutableContact) with a CNContact marked for deletion).

内容的提问来源于stack exchange,提问作者Fabio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:17:18