当我尝试访问联系人姓名时,为什么我的应用程序崩溃?

时间:2013-05-20 12:32:09

标签: ios cocoa-touch

我的应用要求用户选择其中一个联系人,然后选择其中一个联系人的地址。我想生成一个“显示名称”用于引用此地址:例如,如果用户选择John Smith的地址之一,则显示名称为“John Smith”,我的UI将其地址称为“John Smith's”地址”。从地址记录中提取此名称的算法如下:

  1. 如果联系人是公司,请使用公司名称。
  2. 如果有名字和姓氏,请使用“firstname lastname”。
  3. 如果有名字,请使用名字。
  4. 如果有姓氏,请使用姓氏。
  5. 使用字符串“Selected Contact”。
  6. 我实现了所有这些逻辑。问题是我有时会在两条标记线之一上看到崩溃(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;
    }
    

1 个答案:

答案 0 :(得分:2)

假设您对dismissViewControllerAnimated:completion:的调用正在解雇人员选择控制器,并且该控制器保留了您的person对象,则在您完成处理之前,您的person可能已取消分配。仅将dismissViewControllerAnimated:completion:调用移至该方法的结尾应该可以解决问题。如果此处理在解除视图控制器之前导致过多延迟,请将person值复制到ARC将为您保留的变量中,关闭视图控制器,然后处理该人员。