CNContactPickerDelegate的contactPickerDidCancel从未被调用过
当我使用没有与之关联的数字的CNContactPickerViewController
选择联系人时,永远不会调用此委托方法。
/*! * @abstract Invoked when the picker is closed. * @discussion The picker will be dismissed automatically after a contact or property is picked. */ optional public func contactPickerDidCancel(picker: CNContactPickerViewController)
如果我选择一个有号码的联系人,则会调用它。 但是从方法文档来看,无论如何都应该调用它。
我的问题是,如果用户选择没有号码的联系人,我需要提供一个UIAlertController
。 但是,只有在CNContactPickerViewController
才能执行此操作。
我可以通过在viewDidAppear
使用一些逻辑来变得非常hacky但似乎应该有一个更清洁的方式。
唯一剩下的委托方法是:
/*! * @abstract Singular delegate methods. * @discussion These delegate methods will be invoked when the user selects a single contact or property. */ optional public func contactPicker(picker: CNContactPickerViewController, didSelectContact contact: CNContact) optional public func contactPicker(picker: CNContactPickerViewController, didSelectContactProperty contactProperty: CNContactProperty) /*! * @abstract Plural delegate methods. * @discussion These delegate methods will be invoked when the user is done selecting multiple contacts or properties. * Implementing one of these methods will configure the picker for multi-selection. */ optional public func contactPicker(picker: CNContactPickerViewController, didSelectContacts contacts: [CNContact]) optional public func contactPicker(picker: CNContactPickerViewController, didSelectContactProperties contactProperties: [CNContactProperty])
这对于确定CNContactPickerViewController
实际离开屏幕没有帮助。
(Xcode8 / swift2.3 / iOS10)
您可以弹出这样的提醒。 您还可以添加一个“再试一次”按钮并重新启动选择器。
func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) { let name = CNContactFormatter.string(from: contact, style: .fullName) let phones = contact.phoneNumbers if phones.count == 0 { let alertController = UIAlertController(title: "Error", message: "\(name) has no phone numbers", preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "Ok", style: .default) { (action) in }) picker.dismiss(animated: false){ self.present(alertController, animated: true) {} } } //Do stuff here }
我同意这似乎很奇怪你需要以编程方式解雇选择器,当它自己解散时。 BTW for macOS有你需要的委托方法:
- (void)contactPickerWillClose:(CNContactPicker *)picker; // In macOS, called when the contact picker's popover is about to close. - (void)contactPickerDidClose:(CNContactPicker *)picker; // In macOS, called when the contact picker's popover has closed.
无论如何,由于某些原因,这些委托方法不适用于iOS开发人员。 下面是另一种处理这种情况的方法:由于CNContactPickerViewController
是UIViewController
类的CNContactPickerViewController
程序,它自动有这样的方法:
- (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing - (void)viewDidDisappear:(BOOL)animated; // Called after the view was dismissed, covered or otherwise hidden. Default does nothing
需要创建自己的这些方法的实现,这些方法将使用委托来判断CNContactPickerViewController
View
是否被解雇或将被解雇。 这是我的Objective-C这种实现的例子:
SKContactPickerViewController.h
#import @protocol SKContactPickerDelegate; @interface SKContactPickerViewController : CNContactPickerViewController @property (weak, nonatomic, nullable) id delegate; @end @protocol SKContactPickerDelegate @required - (void)contactPicker:(SKContactPickerViewController *)picker viewDidDisappear:(BOOL)animated; @optional - (void)contactPicker:(SKContactPickerViewController *)picker viewWillDisappear:(BOOL)animated; @end
SKContactPickerViewController.m
#import "SKContactPickerViewController.h" @implementation SKContactPickerViewController @dynamic delegate; - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; SEL selector = @selector(contactPicker:viewWillDisappear:); if ([self.delegate respondsToSelector:selector]) { [self.delegate contactPicker:self viewWillDisappear:animated]; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; SEL selector = @selector(contactPicker:viewDidDisappear:); if ([self.delegate respondsToSelector:selector]) { [self.delegate contactPicker:self viewDidDisappear:animated]; } } @end
您正在使用联系人选择器的.m文件中的某个位置:
- (void)addFromContacts { SKContactPickerViewController *contactPicker = [[SKContactPickerViewController alloc] init]; contactPicker.delegate = self; // contactPicker.displayedPropertyKeys = @[CNContactEmailAddressesKey]; // etc. // display controller [self presentViewController:contactPicker animated:YES completion:nil]; }
最后委托方法:
- (void)contactPicker:(SKContactPickerViewController *)picker didSelectContact:(CNContact *)contact { // your usual implementation } - (void)contactPicker:(SKContactPickerViewController *)picker viewDidDisappear:(BOOL)animated { // Present your UIAlertController here }
它将允许在联系人选择器被解雇后呈现UIAlsertController
。 此外,这种方法仍然允许您使用常规委托方法从Contacts UI获取数据 – 委托属性仍然来自Apple实现。 那是@dynamic delegate;
用于说这个属性将由它的超类实现。 您只需使用两个添加的方法通过自己的SKContactPickerDelegate
扩展CNContactPickerDelegate
协议。