使用 __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 中介绍了管理免费桥接。
我一直在使用以下代码将地址簿联系人的缩略图图像获取到 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 中介绍了管理免费桥接。