简体   繁体   中英

Why does my app crash when I try to access a contact’s name?

My app asks users to select one of their contacts and then one of the contact's addresses. I want to generate a “display name” to use to refer to this address: for example, if the user selects one of John Smith's addresses, the display name is “John Smith” and my UI will refer to his address as “John Smith's address”. The algorithm for extracting this name from the address record is as follows:

  1. If the contact is a business, use the business's name.
  2. If there is a first name and a last name, use “firstname lastname”.
  3. If there is a first name use the first name.
  4. If there is a last name use the last name.
  5. Use the string “Selected Contact”.

I have all this logic implemented. The problem is that I sometimes see crashes ( KERN_INVALID_ADDRESS ) on one of the two marked lines. My app uses ARC, and I don't have a lot of experience with Core Foundation, so I assume I'm doing the memory management or bridging incorrectly. Can anyone tell me what I'm doing wrong, and how to fix the crashes? The relevant two methods are as follows:

- (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;
}

Assuming that your call to dismissViewControllerAnimated:completion: is dismissing the people picker controller, and your person object is retained by that controller, your person is probably deallocated before you are finished processing it. Merely moving the dismissViewControllerAnimated:completion: call to the end of that method should fix the problem. If this processing causes too much of a delay before dismissing the view controller, copy the person value into a variable ARC will retain for you, dismiss the view controller, then process the person.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM