如何为CNContactPickerViewController实现两个不同的CNContactPickerDelegate
同一视图控制器中使用两种CNContactPickerViewController行为的解决方案
你提到的隔离代理的思路完全可行,核心就是创建两个独立的代理类,各自实现对应行为的CNContactPickerDelegate方法,以此区分两种选择器的逻辑,无需对CNContactPickerViewController本身做子类化修改。
步骤1:创建独立的代理类
分别实现两个代理类,各自处理一种选择器行为,通过闭包将选中结果回调给视图控制器:
单个联系人选择代理
class SingleContactPickerDelegate: NSObject, CNContactPickerDelegate { private let completion: (CNContact) -> Void init(completion: @escaping (CNContact) -> Void) { self.completion = completion super.init() } func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { picker.dismiss(animated: true) completion(contact) } func contactPickerDidCancel(_ picker: CNContactPickerViewController) { picker.dismiss(animated: true) } }
多个联系人选择代理
class MultipleContactPickerDelegate: NSObject, CNContactPickerDelegate { private let completion: ([CNContact]) -> Void init(completion: @escaping ([CNContact]) -> Void) { self.completion = completion super.init() } func contactPicker(_ picker: CNContactPickerViewController, didSelect contacts: [CNContact]) { picker.dismiss(animated: true) completion(contacts) } func contactPickerDidCancel(_ picker: CNContactPickerViewController) { picker.dismiss(animated: true) } }
步骤2:在视图控制器中使用
在视图控制器中声明属性持有代理实例(避免因弱引用导致代理被提前释放),分别初始化不同的选择器并绑定对应代理:
class YourViewController: UIViewController { // 持有代理实例,防止被提前释放 private var singleContactDelegate: SingleContactPickerDelegate? private var multipleContactDelegate: MultipleContactPickerDelegate? // 打开单个联系人选择器 func presentSingleContactPicker() { let picker = CNContactPickerViewController() let delegate = SingleContactPickerDelegate { [weak self] selectedContact in // 处理单个联系人选中逻辑 self?.handleSingleContact(selectedContact) self?.singleContactDelegate = nil // 用完释放代理 } singleContactDelegate = delegate picker.delegate = delegate present(picker, animated: true) } // 打开多个联系人选择器 func presentMultipleContactPicker() { let picker = CNContactPickerViewController() let delegate = MultipleContactPickerDelegate { [weak self] selectedContacts in // 处理多个联系人选中逻辑 self?.handleMultipleContacts(selectedContacts) self?.multipleContactDelegate = nil // 用完释放代理 } multipleContactDelegate = delegate picker.delegate = delegate present(picker, animated: true) } // 单个联系人选中后的业务逻辑 private func handleSingleContact(_ contact: CNContact) { // 这里写你的具体处理代码,比如提取联系人信息 } // 多个联系人选中后的业务逻辑 private func handleMultipleContacts(_ contacts: [CNContact]) { // 这里写你的具体处理代码 } }
关键注意事项
- 代理类必须继承自
NSObject:因为CNContactPickerDelegate是基于Objective-C的协议,只有NSObject子类才能正确实现代理方法。 - 必须持有代理实例:UIKit的代理属性都是弱引用,如果不在视图控制器中保留强引用,代理对象会在选择器弹出后被立即释放,导致代理方法无法触发。
这个方案完全隔离两种选择器的行为逻辑,代码职责清晰,避免了子类化带来的耦合问题,完全符合你想要的“仅隔离代理”的需求。
内容的提问来源于stack exchange,提问作者benc
相关产品推荐
相关产品推荐

