2013-05-20 2 views
1

Мое приложение просит пользователей выбрать один из своих контактов, а затем один из адресов контакта. Я хочу создать «отображаемое имя», которое будет использоваться для ссылки на этот адрес: например, если пользователь выбирает один из адресов Джона Смита, отображаемое имя «John Smith», и мой пользовательский интерфейс будет ссылаться на его адрес как «John Smith's адрес". Алгоритм для извлечения этого имени из записи адреса выглядит следующим образом:Почему мое приложение падает, когда я пытаюсь получить доступ к имени контакта?

  1. Если контакт является предприятием, используйте его название.
  2. Если есть имя и фамилия, используйте «firstname lastname».
  3. Если есть имя, используйте имя.
  4. Если используется фамилия, используйте фамилию.
  5. Используйте строку «Выбранный контакт».

У меня есть вся эта логика. Проблема в том, что я иногда вижу сбои (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; 
} 

ответ

2

Предполагая, что ваш призыв к dismissViewControllerAnimated:completion: увольняет контроллер выбора людей, и ваш объект person удерживаются этим контроллером, ваш person вероятно освобождаться, прежде чем вы закончили обработку. Простое удаление вызова dismissViewControllerAnimated:completion: в конце этого метода должно устранить проблему. Если эта обработка вызывает слишком большую задержку до отклонения контроллера вида, скопируйте значение person в переменную ARC, которая сохранит для вас, отпустите контроллер представления и обработайте его.

Смежные вопросы