CoreFoundation框架详细解析(十一) —— 自由桥接
版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.02.01 |
前言
与Foundation框架不同的是,
Core Foundation
框架(CoreFoundation.framework)
是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能。接下来几篇我们一起重新审视和详细的看一下这个框架。感兴趣的可以看上面写的几篇。
1. CoreFoundation框架详细解析(一) —— 基本概览
2. CoreFoundation框架详细解析(二) —— 简介
3. CoreFoundation框架详细解析(三) —— 不透明类型
4. CoreFoundation框架详细解析(四) —— 对象引用
5. CoreFoundation框架详细解析(五) —— 多态函数
6. CoreFoundation框架详细解析(六) —— 对象的种类
7. CoreFoundation框架详细解析(七) —— 命名约定
8. CoreFoundation框架详细解析(八) —— 其他类型
9. CoreFoundation框架详细解析(九) —— 对象比较
10. CoreFoundation框架详细解析(十) —— 检查对象
Toll-Free Bridged Types - 自由桥接类型
Core Foundation框架和Foundation框架中有许多数据类型可以互换使用。 可交换使用的数据类型也称为免费桥接数据类型。 这意味着您可以使用与Core Foundation函数调用的参数相同的数据结构,或者作为Objective-C消息调用的接收方。 例如,NSLocale
(请参阅NSLocale Class Reference)可与Core Foundation 对象CFLocale
(请参阅CFLocale Reference)互换。
并非所有的数据类型都是免费桥接的,尽管他们的名字可能表明它们是。 例如,NSRunLoop
不通过桥接到CFRunLoop
,NSBundle
不通过桥接到CFBundle
,而NSDateFormatter
不通过桥接到CFDateFormatter
。 表1提供了支持免费桥接的数据类型列表。
Note: If you install a custom callback on a Core Foundation collection you are using, including a
NULL
callback, its memory management behavior is undefined when accessed from Objective-C. 注意:如果您在您正在使用的Core Foundation集合上安装自定义回调(包括NULL回调),则从Objective-C访问时,其内存管理行为是不确定的。
Casting and Object Lifetime Semantics - Casting和对象生命周期语义
通过自由的桥接,在你看到例如一个NSLocale *
参数的方法中,你可以传递一个CFLocaleRef
,并且在你看到一个CFLocaleRef
参数的函数中,你可以传递一个NSLocale
实例。 您还必须为编译器提供其他信息:首先,您必须将一种类型转换为另一种类型;另外,你可能不得不指出对象的生命周期语义。
编译器理解返回Core Foundation类型的Objective-C方法,并遵循历史上Cocoa命名约定(参见 Advanced Memory Management Programming Guide)。 例如,编译器知道,在iOS中,由UIColor的CGColor方法返回的CGColor不是拥有的。 您仍然必须使用适当的类型转换,如下例所示:
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
编译器不会自动管理Core Foundation对象的生命周期。 您可以使用cast
(在objc / runtime.h
中定义)或Core Foundation样式的宏(在NSObject.h
中定义)告诉编译器关于对象的所有权语义:
-
__bridge
在Objective-C和Core Foundation之间传递一个指针,但不转让所有权。 -
__bridge_retained
或CFBridgingRetain
将一个Objective-C指针转换为Core Foundation指针,并将所有权转让给您。您有责任调用CFRelease
或相关函数来放弃对象的所有权。 -
__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.
}
Toll-Free Bridged Types - 自由桥接类型
表1列出了Core Foundation和Foundation之间可以互换的数据类型。 对于每一对,表格还列出了OS X之间自由桥接可用的版本。
后记
本篇已结束,后面更精彩~~~