ios - AddressBook - iOS 应用程序崩溃,启用 ARC,接近 CF 对象操作

标签 ios crash abaddressbook core-foundation

我遇到了崩溃,很可能与我无法发现的内存管理有关。

崩溃从来没有发生在我身上,我只知道它的发生是因为我收到了崩溃报告。
这也意味着我必须确认崩溃已修复的唯一当前方法是发布应用程序并等待崩溃报告出现(坏消息)或不出现(我很高兴!)。

崩溃报告摘录:

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x9
Crashed Thread:  0

Thread 0 Crashed:
0   CoreFoundation                      0x375f29e8 0x375e4000 + 59880
1   MyApp                            0x000bf22f -[UIViewController(AddressPicker) fullNameAndAddressFromPerson:identifier:] (UIViewController+AddressPicker.m:108)
2   MyApp                            0x000bf3f9 -[UIViewController(AddressPicker) guessedUserAddress] (UIViewController+AddressPicker.m:161)
3   MyApp                            0x0009cc99 -[RecipientsViewController loadUserAddressFromMyAppSender] (RecipientsViewController.m:190)
4   MyApp                            0x0009c189 -[RecipientsViewController viewDidLoad] (RecipientsViewController.m:78)
5   UIKit                               0x31a5e541 0x31a3c000 + 140609

原代码:

- (NSString *) fullNameAndAddressFromPerson:(ABRecordRef) person identifier:(ABMultiValueIdentifier) identifier {
    NSMutableString *address = [NSMutableString new];

    // Get and add first and last name
    CFStringRef cfFirstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
    NSString *firstName = (NSString *)CFBridgingRelease(cfFirstName);

    CFStringRef cfLastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
    NSString *lastName = (NSString *)CFBridgingRelease(cfLastName);

    [address appendFormat:@"%@ %@\n", firstName ?: @"", lastName ?: @""];


    // Get and add address
    ABMultiValueRef addressMultiValue = ABRecordCopyValue(person, kABPersonAddressProperty);

    CFTypeRef addressRef = ABMultiValueCopyValueAtIndex(addressMultiValue, ABMultiValueGetIndexForIdentifier(addressMultiValue, identifier)); // This is line 108
    CFRelease(addressMultiValue);

    NSDictionary *addressDictionary = (NSDictionary *) (CFBridgingRelease(addressRef));

    if ([addressDictionary isKindOfClass:NSDictionary.class]) {
        [address appendString:ABCreateStringWithAddressDictionary(addressDictionary, YES)];
    }

    return [address stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

更新代码,包括 Nirav 建议的检查:

- (NSString *) fullNameAndAddressFromPerson:(ABRecordRef) person identifier:(ABMultiValueIdentifier) identifier {
    NSMutableString *address = [NSMutableString new];
    NSString *firstName, *lastName;

    // Get and add first and last name
    if (person) {
        CFStringRef cfFirstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
        if (cfFirstName) {
            firstName = (NSString *)CFBridgingRelease(cfFirstName);
        }

        CFStringRef cfLastName = ABRecordCopyValue(person, kABPersonLastNameProperty);

        if (cfLastName) {
            lastName = (NSString *)CFBridgingRelease(cfLastName);
        }
    }

    [address appendFormat:@"%@ %@\n", firstName ?: @"", lastName ?: @""];


    // Get and add address
    ABMultiValueRef addressMultiValue = ABRecordCopyValue(person, kABPersonAddressProperty);

    CFTypeRef addressRef;
    if (addressMultiValue && identifier) {
        addressRef = ABMultiValueCopyValueAtIndex(addressMultiValue, ABMultiValueGetIndexForIdentifier(addressMultiValue, identifier));
        CFRelease(addressMultiValue);
    }

    NSDictionary *addressDictionary;

    if (addressRef) {
        addressDictionary = (NSDictionary *) (CFBridgingRelease(addressRef));

        if ([addressDictionary isKindOfClass:NSDictionary.class]) {
            [address appendString:ABCreateStringWithAddressDictionary(addressDictionary, YES)];
        }
    }

    return [address stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}

我想我错过了显而易见的东西,所以我不会只是回复“呃,你是对的”,我会接受可能修复错误的答案指出这段代码可以解决的问题变得更安全和改进。

最佳答案

我在做类似的事情时遇到了类似的崩溃,这就是我所做的:

  • 在使用之前对每个 CFStringRef 进行 null 检查 - 此处:cfFirstName、cfLastName
  • 对返回的每个 ABMultiValueRef 进行 null 检查 - 这里:addressMultiValue

等等。要点是在桥接宏之前执行空检查。

这是为了处理没有填充某些字段的电话簿记录,仅此而已。

关于ios - AddressBook - iOS 应用程序崩溃,启用 ARC,接近 CF 对象操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14655399/

相关文章:

javascript - PhoneGap 2.2.0 支持的 iOS 版本

c# - Xamarin iOS iPad App 崩溃,原因不明

ios - Apple Watch 显示自定义瓦片 map

ios - 不同类型的导航 Controller / View /栏

c# - WP8.1 应用程序在调用 RequestProductPurchaseAsync 时崩溃

crash - 将QT与带有-MT崩溃的DLL一起使用

wcf - 处理需要Web服务的应用程序-处理EndpointNotFoundExceptions

ios - ABPeoplePickerNavigationControllerDelegate 中的 ABMultiValueIdentifier 未正确设置,这是 iOS 错误吗?

c# - ABAddressBook 已弃用,如何使用 ABAddressBook.Create 方法?

ios - 应用程序不要求 iOS 6 上的联系人访问权限