1

私のアプリは、ユーザーに連絡先の 1 つを選択してから、連絡先のアドレスの 1 つを選択するよう求めます。この住所を参照するために使用する「表示名」を生成したいと考えています。たとえば、ユーザーが John Smith の住所の 1 つを選択すると、表示名は「John Smith」となり、UI は彼の住所を「John Smith's」と参照します。住所"。アドレス レコードからこの名前を抽出するアルゴリズムは次のとおりです。

  1. 連絡先がビジネスの場合は、ビジネスの名前を使用します。
  2. 名と姓がある場合は、「firstname lastname」を使用します。
  3. 名がある場合は、名を使用します。
  4. 姓がある場合は、姓を使用します。
  5. 文字列「Selected Contact」を使用します。

このロジックをすべて実装しました。KERN_INVALID_ADDRESS問題は、マークされた 2 つの行のいずれかでクラッシュ ( ) が発生することがあるということです。私のアプリは ARC を使用していますが、Core Foundation の経験があまりないため、メモリ管理またはブリッジングを正しく行っていないと思います。誰が私が間違っているのか、クラッシュを修正する方法を教えてもらえますか? 関連する 2 つの方法は次のとおりです。

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

1 に答える 1

2

dismissViewControllerAnimated:completion:への呼び出しがピープル ピッカー コントローラーを閉じており、personオブジェクトがそのコントローラーによって保持されていると仮定すると、person処理が完了する前にオブジェクトの割り当てが解除される可能性があります。dismissViewControllerAnimated:completion:呼び出しをそのメソッドの最後に移動するだけで、問題が解決するはずです。この処理によってビュー コントローラーを閉じる前に遅延が発生しすぎる場合は、personARC が保持する変数に値をコピーし、ビュー コントローラーを閉じてから、人物を処理します。

于 2013-05-20T13:03:06.277 に答える