OC中的Toll-Free Bridging(桥接)机制
2017-03-13 本文已影响0人
小冰山口
本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java
, 数据结构与算法
, iOS
, 安卓
, python
, flutter
等等, 如有需要, 联系微信tsaievan
.
在开发中, 我们除了要涉及OC对象, 还要涉及Core Foundation类型的对象
-
Core Foundation框架中的对象
CFArrayRef
,CFMutableDictionaryRef
等 -
采用Core Foundation框架惯例的其他框架Core Graphics中的
CGColorSpaceRef
,CGGradientRef
等
编译器不会自动挂历CF对象的生命周期, 所以必须调用CFRetain
,CFRelease
之类的函数来管理CF对象
如果要实现OC和CF对象之间的互相转换, 有几个关键字可以使用
-
__bridge
可以将OC对象转成CF对象,但不会变更所有权 -
__bridge_retained
或者CFBridgingRetain
可以将OC指针转换为CF指针, 同时变更所有权 -
__bridge_transfer
或者CFBridgingRelease
可以将非OC指针转换成OC指针, 同时变更所有权给ARC. ARC负责释放对象
例如你有如下代码:
- (void)logFirstNameOfPerson:(ABRecordRef)person {
NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSLog(@"Person's first name: %@", name);
[name release];
}
你需要替换为:
- (void)logFirstNameOfPerson:(ABRecordRef)person {
NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSLog(@"Person's first name: %@", name);
}
编译器处理OC方法返回的CF对象
编译器知道OC方法返回CF对象是遵守OC命名规则的, 例如, 在iOS中, UIColor方法返回CGColor对象是不被持有的,但还是需要强转, 不过不需要使用__bridge
等关键字
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]];
使用所有权关键字转换函数参数
调用函数或者方法的时候, 函数或者方法的参数类型是指定的, 这个时候就需要强转了.
NSArray *colors = <#An array of colors#>;
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
当所有权没有发生变更时, CF对象还是需要手动调用CFRelease之类的方法释放
- (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.
}