我的应用要求用户选择其中一个联系人,然后选择其中一个联系人的地址。我想生成一个“显示名称”用于引用此地址:例如,如果用户选择John Smith的地址之一,则显示名称为“John Smith”,我的UI将其地址称为“John Smith's”地址”。从地址记录中提取此名称的算法如下:
我实现了所有这些逻辑。问题是我有时会在两条标记线之一上看到崩溃(KERN_INVALID_ADDRESS
)。我的应用程序使用ARC,我对Core Foundation没有太多经验,所以我假设我正在进行内存管理或错误地进行桥接。任何人都可以告诉我我做错了什么,以及如何解决崩溃问题?相关的两种方法如下:
- (BOOL) peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef) person
property:(ABPropertyID) property
identifier:(ABMultiValueIdentifier) identifier
{
[self dismissViewControllerAnimated:YES completion:NULL];
CFTypeRef address = ABRecordCopyValue(person, property);
NSArray *addressArray = (__bridge_transfer NSArray *)ABMultiValueCopyArrayOfAllValues(address);
CFRelease(address);
NSDictionary *addressDict = [addressArray objectAtIndex:0];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressDictionary:addressDict completionHandler:^(NSArray *placemarks, NSError *error) {
if (error || !placemarks || [placemarks count] == 0) {
// tell the user that there was an error
} else {
NSString *name = contactName(person);
NSString *addressName = [NSString stringWithFormat:@"%@’s address", name];
// use `addressName` to refer to this address to the user
}
}];
return NO;
}
NSString* contactName(ABRecordRef person)
{
NSString *name;
// some crashes occur on this line:
CFNumberRef contactType = ABRecordCopyValue(person, kABPersonKindProperty);
if (contactType == kABPersonKindOrganization)
name = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonOrganizationProperty);
if (!name || [name length] == 0 || contactType == kABPersonKindPerson) {
// other crashes occur on this line:
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
if (firstName && [firstName length] > 0 && lastName && [lastName length] > 0)
name = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
else if (firstName && [firstName length] > 0)
name = firstName;
else if (lastName && [lastName length] > 0)
name = lastName;
if (!name || [name length] == 0)
name = @"Selected Contact";
}
CFRelease(contactType);
return name;
}
答案 0 :(得分:2)
假设您对dismissViewControllerAnimated:completion:
的调用正在解雇人员选择控制器,并且该控制器保留了您的person
对象,则在您完成处理之前,您的person
可能已取消分配。仅将dismissViewControllerAnimated:completion:
调用移至该方法的结尾应该可以解决问题。如果此处理在解除视图控制器之前导致过多延迟,请将person
值复制到ARC将为您保留的变量中,关闭视图控制器,然后处理该人员。