【问题标题】:Why does my app crash when I try to access a contact’s name?当我尝试访问联系人姓名时,为什么我的应用程序会崩溃?
【发布时间】:2013-05-15 00:23:54
【问题描述】:

我的应用要求用户选择他们的一位联系人,然后选择一位联系人的地址。我想生成一个“显示名称”来引用这个地址:例如,如果用户选择 John Smith 的地址之一,显示名称是“John Smith”,我的 UI 会将他的地址称为“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;
}

【问题讨论】:

    标签: ios cocoa-touch


    【解决方案1】:

    假设您对dismissViewControllerAnimated:completion: 的调用正在解除人员选择器控制器,并且您的person 对象由该控制器保留,那么您的person 可能在您完成处理之前被释放。只需将 dismissViewControllerAnimated:completion: 调用移到该方法的末尾即可解决问题。如果此处理在关闭视图控制器之前导致过多延迟,请将 person 值复制到 ARC 将为您保留的变量中,关闭视图控制器,然后处理此人。

    【讨论】:

      猜你喜欢
      • 2016-12-24
      • 2017-01-27
      • 1970-01-01
      • 2016-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-29
      相关资源
      最近更新 更多