使用 AdressBookUI 选择特定联系人时如何防止崩溃
How to prevent crash when selecting specific contact using AdressBookUI
我在这条线上崩溃了。
phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(numbers, index));
如果第一个 phone 数字是 selected,我得到索引 1,这是错误的。它应该是 0,因此选择了错误的数字。如果我 select 第二个数字,它给出的索引为 -1,这会使应用程序崩溃。
#pragma mark helper methods
- (void)didSelectPerson:(ABRecordRef)person identifier:(ABMultiValueIdentifier)identifier {
NSString *phoneNumber = @"";
ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (numbers) {
if (ABMultiValueGetCount(numbers) > 0) {
CFIndex index = 0;
if (identifier != kABMultiValueInvalidIdentifier) {
index = ABMultiValueGetIndexForIdentifier(numbers, identifier);
}
phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(numbers, index));
}
CFRelease(numbers);
}
self.numberTextField.text = [NSString stringWithFormat:@"%@", phoneNumber];
}
在处理已删除 phone numbers/emails 的联系人副本时,iOS 8.3(可能是 iOS 8 的早期版本)存在错误。 ABPeoplePickerNavigationController
的文档指出:
In iOS 8 and later bringing up a people-picker navigtion controller does not require the app to have access to a user’s contacts, and the user will not be prompted to grant access. If the app does not itself have access to the user’s contacts, a temporary copy of the contact selected by the user will be returned to the app.
在我的测试中,我有一个具有三个 phone 号码的联系人(我们称它们为 111
、222
和 333
)。 identifier
似乎是固定的、稳定的从零开始的值。因此我的三个 phone 号码是标识符 0
到 2
。如果 phone 号码被删除,标识符不会改变。从零开始的 index
es 用于访问当前的 phone 号码(或电子邮件等)列表,ABMultiValueGetIndexForIdentifier
用于将标识符转换为索引。
在我的测试中,我删除了第一个 phone 号码 111
。这不会更改其余 phone 个号码(222=1
、333=2
)的标识符。
当我使用 ABPeoplePickerNavigationController
并选择第一个 phone 数字 (222
) 时,委托方法 peoplePickerNavigationController: didSelectPerson:property:identifier:
正确传递了标识符 1
。但是,ABMultiValueGetIndexForIdentifier
返回的索引为 1,而不是 0,然后我的应用程序将 phone 数字 333
复制为它认为用户已选择的那个。如果用户选择 333
然后我被正确传递了一个标识符 2
但 ABMultiValueGetIndexForIdentifier
将其转换为 -1
然后对 ABMultiValueCopyValueAtIndex
的不受保护的调用崩溃了。
因此,在处理联系人的 副本 时(这是 iOS 8 中应用未被授权访问地址簿时发生的情况) , iOS 好像是根据真实的联系方式使用标识符,但是索引是基于副本的。该副本似乎忘记了先前删除的 phone 号码,如果用户选择了在先前删除的 phone 之后创建的 phone 号码,标识符到索引的映射就会出错数字。如果用户没有删除 phone 个号码,或者如果他们删除了 phone 个号码 在 他们选择的号码之后,它会起作用。
解决方法是通过使用 ABAddressBookRequestAccessWithCompletion
请求用户访问地址簿的权限来使应用复杂化。一旦授予,应用程序将不会获得所选联系人的 副本,并且标识符到索引的映射工作正常。
我在这条线上崩溃了。
phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(numbers, index));
如果第一个 phone 数字是 selected,我得到索引 1,这是错误的。它应该是 0,因此选择了错误的数字。如果我 select 第二个数字,它给出的索引为 -1,这会使应用程序崩溃。
#pragma mark helper methods
- (void)didSelectPerson:(ABRecordRef)person identifier:(ABMultiValueIdentifier)identifier {
NSString *phoneNumber = @"";
ABMultiValueRef numbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (numbers) {
if (ABMultiValueGetCount(numbers) > 0) {
CFIndex index = 0;
if (identifier != kABMultiValueInvalidIdentifier) {
index = ABMultiValueGetIndexForIdentifier(numbers, identifier);
}
phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(numbers, index));
}
CFRelease(numbers);
}
self.numberTextField.text = [NSString stringWithFormat:@"%@", phoneNumber];
}
在处理已删除 phone numbers/emails 的联系人副本时,iOS 8.3(可能是 iOS 8 的早期版本)存在错误。 ABPeoplePickerNavigationController
的文档指出:
In iOS 8 and later bringing up a people-picker navigtion controller does not require the app to have access to a user’s contacts, and the user will not be prompted to grant access. If the app does not itself have access to the user’s contacts, a temporary copy of the contact selected by the user will be returned to the app.
在我的测试中,我有一个具有三个 phone 号码的联系人(我们称它们为 111
、222
和 333
)。 identifier
似乎是固定的、稳定的从零开始的值。因此我的三个 phone 号码是标识符 0
到 2
。如果 phone 号码被删除,标识符不会改变。从零开始的 index
es 用于访问当前的 phone 号码(或电子邮件等)列表,ABMultiValueGetIndexForIdentifier
用于将标识符转换为索引。
在我的测试中,我删除了第一个 phone 号码 111
。这不会更改其余 phone 个号码(222=1
、333=2
)的标识符。
当我使用 ABPeoplePickerNavigationController
并选择第一个 phone 数字 (222
) 时,委托方法 peoplePickerNavigationController: didSelectPerson:property:identifier:
正确传递了标识符 1
。但是,ABMultiValueGetIndexForIdentifier
返回的索引为 1,而不是 0,然后我的应用程序将 phone 数字 333
复制为它认为用户已选择的那个。如果用户选择 333
然后我被正确传递了一个标识符 2
但 ABMultiValueGetIndexForIdentifier
将其转换为 -1
然后对 ABMultiValueCopyValueAtIndex
的不受保护的调用崩溃了。
因此,在处理联系人的 副本 时(这是 iOS 8 中应用未被授权访问地址簿时发生的情况) , iOS 好像是根据真实的联系方式使用标识符,但是索引是基于副本的。该副本似乎忘记了先前删除的 phone 号码,如果用户选择了在先前删除的 phone 之后创建的 phone 号码,标识符到索引的映射就会出错数字。如果用户没有删除 phone 个号码,或者如果他们删除了 phone 个号码 在 他们选择的号码之后,它会起作用。
解决方法是通过使用 ABAddressBookRequestAccessWithCompletion
请求用户访问地址簿的权限来使应用复杂化。一旦授予,应用程序将不会获得所选联系人的 副本,并且标识符到索引的映射工作正常。