使用 __bridge 转换 ABPersonCopyImageDataWithFormat 的结果以创建 UIImage 时如何防止对象的潜在泄漏?

How to Prevent Potential Leak of an Object when Casting the Result of ABPersonCopyImageDataWithFormat with __bridge to Create a UIImage?

我一直在使用以下代码将地址簿联系人的缩略图图像获取到 UIImage。但是,代码给出了 Core Foundation 警告,对象的潜在泄漏:

// Potential leak of an object

- (UIImage*)contactPictureForPerson:(ABRecordRef)person
{
    if (person != nil && ABPersonHasImageData(person)) {
        return [UIImage imageWithData:(__bridge NSData*)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail)];
    }
    return nil;
}

我应该如何防止潜在的泄漏?

我的代码有问题:ABPersonCopyImageDataWithFormat returns a CFDataRef,没有发布。那是潜在的泄漏。

ARC 不会自动处理 Core Foundation 对象。来自文档:

The compiler does not automatically manage the lifetimes of Core Foundation objects; you must call CFRetain and CFRelease (or the corresponding type-specific variants) as dictated by the Core Foundation memory management rules

作为一个解决方案,我可以将代码分离如下,这样我就可以通过调用 CFRelease 来释放 CFDataRef

- (UIImage*)contactPictureForPerson:(ABRecordRef)person
{
    if (person != nil && ABPersonHasImageData(person)) {
        CFDataRef imageDataRef = ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);
        UIImage* image = [UIImage imageWithData:(__bridge NSData*)imageDataRef];
        CFRelease(imageDataRef);
        return image;
    }
    return nil;
}

请注意,代码使用 桥接 以便在 Objective-C 和 Core Foundation 对象之间进行转换。

普通的 __bridge(如上所用)执行转换而不关心对象的所有权。

作为另一种解决方案,我可以将其切换为使用 __bridge_transfer - 强制转换 将所有权转移给 ARC ; ARC 将为我处理发布。例如

- (UIImage*)contactPictureForPerson:(ABRecordRef)person
{
    if (person != nil && ABPersonHasImageData(person)) {
        return [UIImage imageWithData:(__bridge_transfer NSData*)ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail)];
    }
    return nil;
}

如果您使用的是 Core Foundation,则值得阅读 Apple 关于这些主题的文档。

Transitioning to ARC Release Notes 中介绍了管理免费桥接。

还有 Memory Management Programming Guide for Core Foundation