這篇文檔是比較基礎(chǔ)的,翻譯下來備用。原文地址
介紹
Core Foundation框架和Foundation框架有一些數(shù)據(jù)類型可以交換替代使用。如果數(shù)據(jù)類型可以相互替代,那么這種數(shù)據(jù)類型也被稱為對象橋接類型。這意味著你可以用相同的數(shù)據(jù)結(jié)構(gòu)(對象橋接類型可能本質(zhì)上是由于數(shù)據(jù)結(jié)構(gòu)相同?)作為Core Foundation函數(shù)的調(diào)用參數(shù)或者作為Foundation方法的接收者。例如,NSLocale對象對應(yīng)的是Core Foundation中的CFLocale對象。
不是所有對象都是可以對象橋接的,即使他們的名字暗示他們是對象橋接類型。例如,NSRunLoop與CFRunLoop不能橋接,NSBundle與CFBundle不能橋接,NSDateFormatter與CFDateFormatter不能橋接。文章底部的表格提供了支持對象橋接的數(shù)據(jù)類型。
注意:如果你為Core Foundation集合對象寫了一個在使用它時執(zhí)行的自定義回調(diào), 包括空的回調(diào), 在使用Objective-C訪問這個Core Foundation集合對象時它的內(nèi)存管理行為是不明確的。
聲明和對象生命周期的含義
通過對象橋接,例如在方法中你看到NSLocale *參數(shù),可以傳遞CFLocaleRef,在函數(shù)中看到CFLocaleRef參數(shù),可以傳遞NSLocale *實例。你必須要為編譯器提供其他信息:首先,你必須把一種類型聲明為對應(yīng)的橋接類型;另外,你必須指明對象的生命周期。
編譯器理解Objective-C方法返回的Core Foundation類型并且遵守Cocoa命名習(xí)俗。例如,編譯器知道在iOS中,通過調(diào)用UIColor的CGColor方法返回的CGColor對象并不被認(rèn)可,你仍然必須為其聲明合適的類型,下面代碼塊為例:
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對象的生命周期。你需要告訴編譯器對象的所有權(quán)(請參考我之前翻譯的文檔 [iOS]CoreFoundation - Ownership Policy ),通過聲明或者使用Core Foundation類型的宏:
-
__bridge在Objective-C和Core Foundation之間傳遞了一個指針,但是沒有傳遞對象的所有權(quán)。 -
__bridge_retained或者CFBridgingRetain將一個Objective-C指針轉(zhuǎn)換為Core Foundation指針,并且將Objective-C對象的所有權(quán)交給你(如果要釋放對象需要調(diào)用Release函數(shù))。 -
__bridge_transfer或者CFBridgingRelease將非Objective-C指針移動到Objective-C并且將對象的所有權(quán)交給ARC,所以ARC有責(zé)任在不使用該對象的時候?qū)⑵溽尫拧?br> 上述中部分內(nèi)容體現(xiàn)在下面的例子中:
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內(nèi)存管理規(guī)則 的 Core Foundation內(nèi)存管理函數(shù) 的使用:
- (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之間橋接的數(shù)據(jù)類型的列表,同時列出了每一對數(shù)據(jù)類型開始生效的macOS版本。