Мое приложение просит пользователей выбрать один из своих контактов, а затем один из адресов контакта. Я хочу создать «отображаемое имя», которое будет использоваться для ссылки на этот адрес: например, если пользователь выбирает один из адресов Джона Смита, отображаемое имя «John Smith», и мой пользовательский интерфейс будет ссылаться на его адрес как «John Smith's адрес". Алгоритм для извлечения этого имени из записи адреса выглядит следующим образом:Почему мое приложение падает, когда я пытаюсь получить доступ к имени контакта?
- Если контакт является предприятием, используйте его название.
- Если есть имя и фамилия, используйте «firstname lastname».
- Если есть имя, используйте имя.
- Если используется фамилия, используйте фамилию.
- Используйте строку «Выбранный контакт».
У меня есть вся эта логика. Проблема в том, что я иногда вижу сбои (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;
}