当点击地址簿中的任何联系人(在我的应用程序内)时,它在 iOS 10 beta 上崩溃,但在 iOS 9 版本上工作正常;
这是崩溃日志
*** Terminating app due to uncaught exception 'CNPropertyNotFetchedException', reason: 'A property was not requested when contact was fetched.'
*** First throw call stack:
(0x1cf11a07 0x1c62af63 0x1cf1194d 0x246f0f4f 0x246c6a71 0x1ce355eb 0x1ce2e19b 0x246c69cf 0x246c6883 0x25e4a375 0x2538f283 0x254204ef 0x25420bb1 0xe9da97 0xe9da83 0xea2321 0x1cecf18f 0x1cecd477 0x1ce1e6bd 0x1ce1e549 0x1e54ebfd 0x21f961e3 0x21f90947 0x966c9 0x1ca9e507)
libc++abi.dylib: terminating with uncaught exception of type NSException
这是在我的应用程序中打开地址簿的代码:
-(void)showContactPicker {
__weak RecieverSelectorViewController *weakSelf = self;
ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
picker.modalPresentationStyle = UIModalPresentationFullScreen;
picker.modalTransitionStyle = UIModalPresentationPopover;
[self presentViewController:picker
animated:YES
completion:^{
[weakSelf hideLoadingAnimation];
// animation to show view controller has completed.
}];
}
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
[self setSelectedPerson:person];
}
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person {
[self setSelectedPerson:person];
}
-(void)setSelectedPerson:(ABRecordRef)person {
NSString *contactName = CFBridgingRelease(ABRecordCopyCompositeName(person));
ABMultiValueRef phoneRecord = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phoneRecord, 0);
self.isSenderReciever = NO;
NSString *phone = [PorterUtils
extraLast10DigitsFromDigitString:[PorterUtils
extractNumberFromText:(__bridge_transfer NSString *)phoneNumber]];
//Handling Social Media Contacts - Crash
if(contactName.length>0 && phone.length>0){
[self setRecieverName:contactName
number:phone];
CFRelease(phoneRecord);
}
}
仅在 iOS 10 公开测试版上崩溃。
尝试使用CNContactPickerViewController(iOS9及以上):
添加ContactsUI.framework,导入框架,声明委托CNContactPickerDelegate。
CNContactPickerViewController *peoplePicker = [[CNContactPickerViewController alloc] init];
peoplePicker.delegate = self;
NSArray *arrKeys = @[CNContactPhoneNumbersKey]; //display only phone numbers
peoplePicker.displayedPropertyKeys = arrKeys;
[self presentViewController:peoplePicker animated:YES completion:nil];
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty{
CNPhoneNumber *phoneNumber = contactProperty.value;
NSString *phoneStr = phoneNumber.stringValue;
}
地址簿 API 在 iOS 9 中已被弃用,取而代之的是更加面向对象的联系人框架。
不要使用 ABPeoplePickerViewController,而是移至 CNContactPickerViewController。
检查您是否提供了有效的密钥,例如
@[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey]
当他们向 CNContact 对象请求时。
例如:如果您需要调用 contact.emailAddresses,则必须从 (CNContactEmailAddressesKey) 数组提供。
iOS 10 不允许访问联系人,直到我们提到为什么我们使用它。打开你的 plist 作为源代码,在 dict 下添加以下代码现在再次运行它。
<key>NSContactsUsageDescription</key>
<string>$(PRODUCT_NAME) uses Contact</string>
IOS 10 现在需要用户权限才能访问媒体库、照片、 相机和其他类似的硬件。解决这个问题的方法是添加 将他们的密钥放入 info.plist 中,并为用户提供我们的描述 使用他们的数据,iOS已经需要访问权限 麦克风、相机和媒体库较早(iOS6、iOS7),但自此 iOS10 如果您不提供说明原因,应用程序将会崩溃 正在请求许可。
您可以在 Info.plist 文件中指定所有 Cocoa Key 的列表
照片:
Key : Privacy - Photo Library Usage Description
Value : $(PRODUCT_NAME) photo use
麦克风:
Key : Privacy - Microphone Usage Description
Value : $(PRODUCT_NAME) microphone use
相机:
Key : Privacy - Camera Usage Description
Value : $(PRODUCT_NAME) camera use
斯威夫特3
// This example allows the display and selection of email addresses only.
if #available(iOS 9.0, *) {
let picker = CNContactPickerViewController()
let arrKeys = [CNContactEmailAddressesKey] // array of properties to display
picker.displayedPropertyKeys = arrKeys
picker.delegate = self
present(picker, animated: true, completion: nil)
}
代表示例
@available(iOS 9.0, *)
func contactPicker(_ picker: CNContactPickerViewController, didSelect contactProperty: CNContactProperty) {
let emailAddress = contactProperty.value as? String
}
首先在
NSContactsUsageDescription
中添加info.plist
,然后将控制器呈现在AB请求访问块中,如下所示。
ABAddressBookRequestAccessWithCompletion(contactPicker, { success, error in
if success {
self.presentViewController(self.contactPicker, animated: true, completion: nil)
}
})
您可能忘记指定您获取的所有密钥。假设您在自定义
contact.middleName
映射中使用 ContactModel
,但忘记在请求中指定 CNContactMiddleNameKey
。
使用请求中的键获取联系人的示例:
let keys = [
CNContactGivenNameKey as CNKeyDescriptor,
CNContactFamilyNameKey as CNKeyDescriptor,
CNContactMiddleNameKey as CNKeyDescriptor,
CNContactPhoneNumbersKey as CNKeyDescriptor,
CNContactImageDataKey as CNKeyDescriptor
]
let request = CNContactFetchRequest(keysToFetch: keys)
try store.enumerateContacts(with: request) { contact, _ in
let newContact = ContactModel(
id: contact.identifier,
name: contact.givenName + contact.middleName,
surname: contact.familyName,
image: contact.imageData,
numbers: contact.phoneNumbers.compactMap( { $0.value.stringValue } )
)
contacts.append(newContact)
}