这篇文档是比较基础的,翻译下来备用。原文地址
介绍
Core Foundation框架和Foundation框架有一些数据类型可以交换替代使用。如果数据类型可以相互替代,那么这种数据类型也被称为对象桥接类型。这意味着你可以用相同的数据结构(对象桥接类型可能本质上是由于数据结构相同?)作为Core Foundation函数的调用参数或者作为Foundation方法的接收者。例如,NSLocale
对象对应的是Core Foundation中的CFLocale
对象。
不是所有对象都是可以对象桥接的,即使他们的名字暗示他们是对象桥接类型。例如,NSRunLoop
与CFRunLoop
不能桥接,NSBundle
与CFBundle
不能桥接,NSDateFormatter
与CFDateFormatter
不能桥接。文章底部的表格提供了支持对象桥接的数据类型。
注意:如果你为Core Foundation集合对象写了一个在使用它时执行的自定义回调, 包括空的回调, 在使用Objective-C访问这个Core Foundation集合对象时它的内存管理行为是不明确的。
声明和对象生命周期的含义
通过对象桥接,例如在方法中你看到NSLocale *
参数,可以传递CFLocaleRef
,在函数中看到CFLocaleRef
参数,可以传递NSLocale *
实例。你必须要为编译器提供其他信息:首先,你必须把一种类型声明为对应的桥接类型;另外,你必须指明对象的生命周期。
编译器理解Objective-C方法返回的Core Foundation类型并且遵守Cocoa命名习俗。例如,编译器知道在iOS中,通过调用UIColor
的CGColor
方法返回的CGColor
对象并不被认可,你仍然必须为其声明合适的类型,下面代码块为例:
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; // 不声明为id类型会报出"Incompatible pointer types sending 'CGColorRef _Nonnull' (aka 'struct CGColor *') to parameter of type 'id _Nonnull' "这个警告
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
编译器不自动管理Core Foundation对象的生命周期。你需要告诉编译器对象的所有权(请参考我之前翻译的文档 [iOS]CoreFoundation - Ownership Policy ),通过声明或者使用Core Foundation类型的宏:
-
__bridge
在Objective-C
和Core Foundation
之间传递了一个指针,但是没有传递对象的所有权。 -
__bridge_retained
或者CFBridgingRetain
将一个Objective-C
指针转换为Core Foundation
指针,并且将Objective-C
对象的所有权交给你(如果要释放对象需要调用Release
函数)。 -
__bridge_transfer
或者CFBridgingRelease
将非Objective-C
指针移动到Objective-C
并且将对象的所有权交给ARC,所以ARC有责任在不使用该对象的时候将其释放。
上述中部分内容体现在下面的例子中:
NSLocale *gbNSLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"];
CFLocaleRef gbCFLocale = (__bridge CFLocaleRef)gbNSLocale;
CFStringRef cfIdentifier = CFLocaleGetIdentifier(gbCFLocale);
NSLog(@"cfIdentifier: %@", (__bridge NSString *)cfIdentifier);
// Logs: "cfIdentifier: en_GB"
CFLocaleRef myCFLocale = CFLocaleCopyCurrent();
NSLocale *myNSLocale = (NSLocale *)CFBridgingRelease(myCFLocale);
NSString *nsIdentifier = [myNSLocale localeIdentifier];
CFShow((CFStringRef)[@"nsIdentifier: " stringByAppendingString:nsIdentifier]);
// Logs identifier for current locale
接下来的例子显示了遵守 Core Foundation内存管理规则
的 Core Foundation内存管理函数
的使用:
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat locations[2] = {0.0, 1.0};
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object.
CGPoint startPoint = CGPointMake(0.0, 0.0);
CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));
CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint,
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient); // Release owned Core Foundation object.
}
对象桥接类型
下表提供了一个支持Core Foundation
和Foundation
之间桥接的数据类型的列表,同时列出了每一对数据类型开始生效的macOS版本。
网友评论