[iOS] Core Foundation - Toll-Free Bridged Types

这篇文档是比较基础的,翻译下来备用。原文地址

介绍

Core Foundation框架和Foundation框架有一些数据类型可以交换替代使用。如果数据类型可以相互替代,那么这种数据类型也被称为对象桥接类型。这意味着你可以用相同的数据结构(对象桥接类型可能本质上是由于数据结构相同?)作为Core Foundation函数的调用参数或者作为Foundation方法的接收者。例如,NSLocale对象对应的是Core Foundation中的CFLocale对象。
不是所有对象都是可以对象桥接的,即使他们的名字暗示他们是对象桥接类型。例如,NSRunLoopCFRunLoop不能桥接,NSBundleCFBundle不能桥接,NSDateFormatterCFDateFormatter不能桥接。文章底部的表格提供了支持对象桥接的数据类型。

注意:如果你为Core Foundation集合对象写了一个在使用它时执行的自定义回调, 包括空的回调, 在使用Objective-C访问这个Core Foundation集合对象时它的内存管理行为是不明确的。

声明和对象生命周期的含义

通过对象桥接,例如在方法中你看到NSLocale *参数,可以传递CFLocaleRef,在函数中看到CFLocaleRef参数,可以传递NSLocale *实例。你必须要为编译器提供其他信息:首先,你必须把一种类型声明为对应的桥接类型;另外,你必须指明对象的生命周期。
编译器理解Objective-C方法返回的Core Foundation类型并且遵守Cocoa命名习俗。例如,编译器知道在iOS中,通过调用UIColorCGColor方法返回的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类型的宏:

  • __bridgeObjective-CCore 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 FoundationFoundation之间桥接的数据类型的列表,同时列出了每一对数据类型开始生效的macOS版本。

Core Foundation type Foundation class Availability
CFArrayRef NSArray OS X 10.0
CFAttributedStringRef NSAttributedString OS X 10.4
CFBooleanRef NSNumber OS X 10.0
CFCalendarRef NSCalendar OS X 10.4
CFCharacterSetRef NSCharacterSet OS X 10.0
CFDataRef NSData OS X 10.0
CFDateRef NSDate OS X 10.0
CFDictionaryRef NSDictionary OS X 10.0
CFErrorRef NSError OS X 10.5
CFLocaleRef NSLocale OS X 10.4
CFMutableArrayRef NSMutableArray OS X 10.0
CFMutableAttributedStringRef NSMutableAttributedString OS X 10.4
CFMutableCharacterSetRef NSMutableCharacterSet OS X 10.0
CFMutableDataRef NSMutableData OS X 10.0
CFMutableDictionaryRef NSMutableDictionary OS X 10.0
CFMutableSetRef NSMutableSet OS X 10.0
CFMutableStringRef NSMutableString OS X 10.0
CFNullRef NSNull OS X 10.2
CFNumberRef NSNumber OS X 10.0
CFReadStreamRef NSInputStream OS X 10.0
CFRunLoopTimerRef NSTimer OS X 10.0
CFSetRef NSSet OS X 10.0
CFStringRef NSString OS X 10.0
CFTimeZoneRef NSTimeZone OS X 10.0
CFURLRef NSURL OS X 10.0
CFWriteStreamRef NSOutputStream OS X 10.0

你可能感兴趣的:([iOS] Core Foundation - Toll-Free Bridged Types)