2013-05-20 1 views
1

내 앱은 사용자에게 연락처 중 하나를 선택한 다음 연락처의 주소 중 하나를 선택하도록 요청합니다. 이 주소를 나타내는 데 사용할 "표시 이름"을 생성하려고합니다. 예를 들어 사용자가 John Smith의 주소 중 하나를 선택하면 표시 이름은 "John Smith"이고 UI는 그의 주소를 "John Smith 's 주소". 주소록에서이 이름을 추출하는 알고리즘은 다음과 같습니다.연락처 이름에 액세스하려고 할 때 내 앱이 중단되는 이유는 무엇입니까?

  1. 연락처가 업체 인 경우 업체명을 사용하십시오.
  2. 이름과 성이 있으면 "성 이름"을 사용하십시오.
  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: 호출을 이동하면 문제가 해결됩니다. 이 처리로 인해보기 컨트롤러를 삭제하기 전에 지연이 너무 많이 발생하면 ARC가 유지할 변수에 person 값을 복사하고보기 컨트롤러를 닫은 다음 해당 사용자를 처리하십시오.

관련 문제