精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一篇文章徹底弄清ARC始末

移動開發(fā) iOS
Xcode提供了自動化的工具,完成ARC轉(zhuǎn)換過程中需要手工操作的部分(例如刪除retain和release方法調(diào)用),并且?guī)椭阍谶w移過程中不能自動完成的操作(選擇Edit->Refactor->Convert to Objective-C ARC)。遷移工具將工程中的所有文件使用ARC進行轉(zhuǎn)換。如果你覺得在某些文件中使用手動引用計數(shù)會更方便,那么你也可以選擇在單獨文件中使用ARC。

自動引用計數(shù)(ARC)是編譯器的一個特色,提供了Objective-C對象的自動內(nèi)存管理機制。比起不得不考慮retain和release操作,ARC讓你更加專注于應用中那些有趣的代碼,如對象圖,對象關(guān)系。

摘要(Summary)

通過在編譯期添加代碼的方式,ARC保證所有對象按需存在,按需釋放。從概念上來講,它與手動引用計數(shù)(參見 Advanced Memory Management Programming Guide)有著相同的內(nèi)存管理約定,二者都會為你添加合適的內(nèi)存管理方法調(diào)用。 為了編譯器能生成正確的代碼,ARC限定了你可以使用的一些方法,以及toll-free橋接的使用方式(參見 “Toll-Free Bridged Types”).與此同時ARC還為對象引用(object references )和聲明式屬性(declared properties)引進了新的生命周期限定符(lifetime qualifiers )。 ARC適用于OS X v10.6和v10.7(64位)下的Xcode4.2,以及IOS 4和IOS5.OS X v10.6和IOS4不支持弱引用。Xcode提供了自動化的工具,完成ARC轉(zhuǎn)換過程中需要手工操作的部分(例如刪除retain和release方法調(diào)用),并且?guī)椭阍?遷移過程中不能自動完成的操作(選擇Edit->Refactor->Convert to Objective-C ARC)。遷移工具將工程中的所有文件使用ARC進行轉(zhuǎn)換。如果你覺得在某些文件中使用手動引用計數(shù)會更方便,那么你也可以選擇在單獨文件中使用ARC。
參見:
Advanced Memory Management Programming Guide
Memory Management Programming Guide for Core Foundation

ARC概述(ARC Overview)

ARC會評估對象所需的生命期,并會在編譯期為你自動插入合適的內(nèi)存管理調(diào)用方法,取代之前你不得不考慮何時需要使用 retainrelease以及 autorelease的操作方式。編譯器也會為你生成合適的 dealloc方法。總的來說,如果你僅使用ARC,傳統(tǒng)的Cocoa命名規(guī)范只會在你需要與使用手動引用計數(shù)的代碼交互時才是重要的。一個完整正確的Person類的實現(xiàn)看起來可能是這樣的:

  1. @interface Person : NSObject 
  2. @property NSString *firstName; 
  3. @property NSString *lastName; 
  4. @property NSNumber *yearOfBirth; 
  5. @property Person *spouse; 
  6. @end 
  7. @implementation Person 
  8. @end

(對象屬性(properties)默認是強類型的( strong); strong屬性描述于 “ARC Introduces New Lifetime Qualifiers.”)
使用ARC,你可以如下實現(xiàn)一個 contrived方法:

  1. - (void)contrived 
  2.     Person *aPerson = [[Person alloc] init]; 
  3.     [aPerson setFirstName:@"William"]; 
  4.     [aPerson setLastName:@"Dudney"]; 
  5.     [aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]]; 
  6.     NSLog(@"aPerson: %@", aPerson); 

ARC會維護內(nèi)存管理,所以 Person和 NSNumber對象都不會泄露。
你也可以安全的實現(xiàn) Person類中的 takeLastnameFrom:方法。

  1. - (void)takeLastNameFrom:(Person *)person { 
  2.     NSString *oldLastname = [self lastName]; 
  3.     [self setLastName:[person lastName]]; 
  4.     NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]); 

ARC保證 oldLastName在 NSLog語句之前不會被釋放。
【ARC強制執(zhí)行新規(guī)則】(ARC Enforces New Rules)
為了正常運轉(zhuǎn),ARC使用了一些在使用其它編譯模式下沒有的新規(guī)則。這些規(guī)則意在提供完全可靠的內(nèi)存管理模型;在某些情況下,它們僅使用***實踐方法,在其它情況下,它們僅簡化你的代碼或明顯的做出推論告知你不需要處理內(nèi)存管理。如果
你違反了這些規(guī)則,你會馬上得到一個編譯期錯誤,而不是在運行期可能會顯現(xiàn)的一個狡猾的bug。
1.不能顯示的調(diào)用dealloc,實現(xiàn)或調(diào)用 retain, release, retainCount,或 autorelease。
同樣也不要能使用 @selector(retain), @selector(release), 等等類似的選擇器。
如果你需要管理資源而不是釋放實例變量,那你可以實現(xiàn) dealloc方法。你不需要(事實上你不能)釋放實例變量,但你可能需要在系統(tǒng)類和其它的未使用ARC代碼中調(diào)用 [systemClassInstance setDelegate:nil] 方法。
在ARC中自定義的 dealloc方法不要調(diào)用 [super dealloc]方法(它實際上會導致編譯器錯誤)。到super的鏈式調(diào)用是自動的并且是編譯器強制執(zhí)行的。
你仍可以在Core Foundation樣式的的對象上,使用 CFRetain, CFRelease,和其它相關(guān)的函數(shù)。
2.你不能使用 NSAllocateObject 或 NSDeallocateObject
你使用 alloc來創(chuàng)建對象;運行時系統(tǒng)會注意釋放這些對象。
3.你不能在C語言結(jié)構(gòu)體中使用對象指針。 與其使用一個結(jié)構(gòu)體( struct),不如創(chuàng)建一個Objective-C類來管理數(shù)據(jù)。
4. id與 void*之間不能隨意轉(zhuǎn)換
你必須使用特定的類型轉(zhuǎn)換來告訴編譯器對象的生命周期。你需要在Objective-C對象和以函數(shù)參數(shù)傳入的Core Foundation類型值之間進行這樣的轉(zhuǎn)換。有關(guān)詳情,參見 “Managing Toll-Free Bridging”
5.你不能使用 NSAutoreleasePool對象
ARC 提供了 @autoreleasepool來代替。這比 NSAutoreleasePool更高效。
6.你不能使用內(nèi)存區(qū)(memory zones)。
再也沒有使用 NSZone的必要了——現(xiàn)代的Obj-C運行時會永遠忽略它。
為了允許與自動retain-release的代碼進行交互,ARC在方法命名上加上了一個約束:
你不能以 new為開頭命名一個訪問器的名字。這反過來意味著你不必聲明一個以new開頭的屬性,除非你指定一個不同名稱的getter方法:

  1. // Won't work: 
  2. @property NSString *newTitle; 
  3. // Works: 
  4. @property (getter=theNewTitle) NSString *newTitle; 

【ARC引入新的生命周期限定符】(ARC Introduces New Lifetime Qualifiers)
ARC為對象引入了幾種新的生命周期限定符,以及弱類型引用( weak references)。弱類型應用不會延長它所指向?qū)ο蟮纳芷冢坏ο鬀]有強引用指向?qū)ο髸r,弱引用會自動變?yōu)? nil
在程序中,你應該充分利用這些限定符來管理對象圖。尤其是,ARC不能阻止強引用循環(huán)(strong reference cycles,之前稱為retain cycles,參見“Practical Memory Management”)的發(fā)生。審慎的使用弱類型關(guān)系會幫助你避免創(chuàng)建強引用循環(huán)。
【Property的屬性】(Property Attributes)
weak和 strong關(guān)鍵字是新引入的property聲明屬性,如下例所示:

  1. // 以下聲明等價于 @property(retain) MyClass *myObject; 
  2. @property(strong) MyClass *myObject; 
  3. // 以下聲明等價于"@property(assign) MyClass *myObject;" 
  4. // 不同之處在于如果MyClass的實例變量釋放時,其屬性值會設置為nil,而不會保存為一個野指針 
  5. @property(weak) MyClass *myObject; 

ARC下,對象類型的聲明默認為 strong
【變量限定符】(Variable Qualifiers)
你可以向使用其它變量的限定符那樣,比如說, const,來使用以下生命周期限定符,

  1. __strong 
  2. __weak 
  3. __unsafe_unretained 
  4. __autoreleasing 

__strong是默認的。只要有強類型指針指向一個對象,那么該對象會一直”生存“下去。
__weak表明一個不會維持所持對象生命期的引用。當沒有強引用指向該對象時,弱引用會設置為nil。
__unsafe_unretained指定一個引用,該引用不會維持所持對象的生命期,并且在沒有強引用指向?qū)ο髸r也不會設置為nil。如果它所指向的對象已經(jīng)被釋放,那么它會成為一個野指針。
__autoreleasing 用以指示以引用(id*)傳入的參數(shù)并在retun后自動釋放。
你應該正確的修飾變量。在對象變量的聲明時使用限定符的正確格式為:

  1. ClassName * qualifier variableName; 

例如:

  1. MyClass * __weak myWeakReference; 
  2. MyClass * __unsafe_unretained myUnsafeReference; 

從技術(shù)上講其它的變體寫法都是錯誤的,但編譯器都會”寬恕“它們。要弄清該問題,參見http://cdecl.org/.
在堆棧上使用 __weak變量時要當心。考慮以下的例子:

  1. NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; 
  2. NSLog(@"string: %@", string); 

雖然 string是在初始化賦值之后使用,但是在賦值的時候并沒有其它強引用指向字符串對象;因此字符串對象會馬上釋放掉。log語句顯示 stirng的值為 null。(編譯器對這種情況會提示警告)
你也要注意通過引用方式傳入的對象。以下代碼會正常運轉(zhuǎn)

  1. NSError *error; 
  2. BOOL OK = [myObject performOperationWithError:&error]; 
  3. if (!OK) { 
  4.     // Report the error. 
  5.     // ... 

而error的聲明是隱式的:

  1. NSError * __strong e; 

方法的聲明通常是: 

  1. -(BOOL)performOperationWithError:(NSError * __autoreleasing *)error; 

因此編譯器會重寫代碼:

  1. NSError * __strong error; 
  2. NSError * __autoreleasing tmp = error; 
  3. BOOL OK = [myObject performOperationWithError:&tmp]; 
  4. error = tmp; 
  5. if (!OK) { 
  6.     // Report the error. 
  7.     // ... 

本地變量聲明( __strong)和參數(shù)( __autoreleasing)之間的區(qū)別導致編譯器創(chuàng)建臨時變量。在獲取__strong變量的地址時你可以通過將參數(shù)聲明為 id __storng*來獲得其原始指針。或者你可以將變量聲明為 __autoreleasing。


不要走開,下頁內(nèi)容更勁爆

#p#

【使用生命周期限定符來避免強類型循環(huán)引用】(Use Lifetime Qualifiers to Avoid Strong Reference Cycles)
你可以使用生命周期限定符來避免強類型循環(huán)引用。例如,通常如果你的對象圖形成于父-子層級結(jié)構(gòu)中,父對象需要引用它的子對象,反之亦然, 那么你構(gòu)造parent-to-child的關(guān)系為強類型,child-to-parent的關(guān)系為弱類型。其它情況可能會更加微妙,尤其是在涉及到 block對象時。
在手動引用技術(shù)的模式下, __block id x,不會保留x。在ARC模式下, __block id x;默認會保留x(就像其它值一樣)。為了在ARC下達到手動引用技術(shù)的效果,你可以使用 __unsafe__unretained __block id x ;然而,就像 __unsafe_unretained名字蘊含的那樣,擁有一個未保留變量(non-retained variable)是危險的(因為他可能是一個野指針),因此***不要使用。有兩個更好的選擇是要么使用 __weak(如果你不需要支持IOS4或OS X v10.6),要門設置 __block值nil來打破循環(huán)引用。
以下的代碼片段說明了在手動引用技術(shù)下時常會使用的模式。

  1. MyViewController *myController = [[MyViewController alloc] init…]; 
  2. // ... 
  3. myController.completionHandler =  ^(NSInteger result) { 
  4.    [myController dismissViewControllerAnimated:YES completion:nil]; 
  5. }; 
  6. [self presentViewController:myController animated:YES completion:^{ 
  7.    [myController release]; 
  8. }]; 

如上所屬,你可以使用 __block限定符來替代,并在 completion處理方法中將myController的值設置為nil:

  1. MyViewController * __block myController = [[MyViewController alloc] init…]; 
  2. // ... 
  3. myController.completionHandler =  ^(NSInteger result) { 
  4.     [myController dismissViewControllerAnimated:YES completion:nil]; 
  5.     myController = nil; 
  6. }; 

或者,你可以使用一個臨時的 __weak變量。以下代碼列舉了一個簡單的實現(xiàn):

  1. MyViewController *myController = [[MyViewController alloc] init…]; 
  2. // ... 
  3. MyViewController * __weak weakMyViewController = myController; 
  4. myController.completionHandler =  ^(NSInteger result) { 
  5.     [weakMyViewController dismissViewControllerAnimated:YES completion:nil]; 
  6. }; 

而對于特殊的循環(huán),你應該使用:

  1. MyViewController *myController = [[MyViewController alloc] init…]; 
  2. // ... 
  3. MyViewController * __weak weakMyController = myController; 
  4. myController.completionHandler =  ^(NSInteger result) { 
  5.     MyViewController *strongMyController = weakMyController; 
  6.     if (strongMyController) { 
  7.         // ... 
  8.        [strongMyController dismissViewControllerAnimated:YES completion:nil]; 
  9.         // ... 
  10.     } 
  11.     else { 
  12.         // Probably nothing... 
  13.     } 
  14. }; 

某些情況下如果一個類不兼容__ weak,你可以使用 __unsafe_unretained。但這也不適用于特殊的循環(huán),因為在實際問題中驗證 __unsafe_unretained指針是否仍有效或是否仍指向相同的對象,是非常困難或根本不可能實現(xiàn)的。
【ARC使用新聲明來管理自動釋放池】(ARC Uses a New Statement to Manage Autorelease Pools)
使用ARC,你不能直接使用NSAutoreleasePool類來管理自動釋放池。相反,你需要使用 @autoreleasepool塊:

  1. @autoreleasepool { 
  2.      // Code, such as a loop that creates a large number of temporary objects. 

這個簡單的結(jié)構(gòu)讓編譯器來判斷引用計數(shù)的狀態(tài)。在入口,自動釋放池會被push。在正常退出( break,return,goto,fall-through,dengd)自動釋放池會被pop。出于對已有代碼兼容性的考慮,如果因異常導致退出,自動釋放池將不會被pop。
該語法在所有Objecti-C模式下都可用。相比使用 NSAutoreleasePool類來說, @autoreleasepool更加高效;因此鼓勵你在使用 NSAutoreleasePool的地方使用 @autoreleasepool。
【跨平臺下Outlets管理保持一致的模式】(Patterns for Managing Outlets Become Consistent Across Platforms)

ARC下的IOS和OS X中聲明outlets的模式已經(jīng)發(fā)生變化,并且在跨平臺下保持一致性。你通常應該接受的是:outlets應該是 weak的,除了那些在nib文件(或storyboard屏)中File‘s Owner指向的***對象應該是 strong的。
Resource Programming Guide.中的 ”Nib Files“做出了全面的解釋。
【堆變量會初始化為nil】(Stack Variables Are Initialized with nil)
使用ARC,strong,weak,以及autoreleasing的堆變量現(xiàn)在會隱式的初始化為nil,例如:

  1. - (void)myMethod { 
  2.     NSString *name; 
  3.     NSLog(@"name: %@", name); 

輸出的 name的值為null而不可能是程序崩潰。
【使用編譯器指令來啟用或禁用ARC】(Use Compiler Flags to Enable and Disable ARC)
使用 -fobjc-arc編譯指令來啟動ARC。如果在某些文件中使用手動引用技術(shù)對你來說更方便些,你可以選擇在單獨的文件上使用ARC。對于默認使用ARC的工程,你可以使用 fno-objc-arc編譯指令來禁用某個文件的ARC。
Xcode4.2及更高版本,OS X v10.6及更高版本(64為應用),IOS4版本或更高版本支持ARC。OS X v10.6和IOS4不支持弱引用。Xcode4.1及早期版本的Xcode不支持ARC。
【管理Toll-Free橋接】(Managing Toll-Free Bridging)
在許多Cocoa應用中,你可以使用Core Foundation樣式的對象,不管是來自于Core Foundation框架本身(例如, CFArrayRefCFMutableDictionaryRef),還是來自于諸如Core Graphics一樣采用Core Foundation約定的框架(你可能使用向 CGColorSpaceRef and CGGradientRef樣式的類型)。
編譯器不會自動管理Core Foundation對象的生命周期;你必須調(diào)用符合Core Founda內(nèi)存管理規(guī)則的CFRetain和CFRelease方法(或者合適的特殊類型變體)來釋放對象。(參見 Memory Management Programming Guide for Core Foundation
如果你在Objective-C對象和Core Foundation樣式對象間執(zhí)行類型轉(zhuǎn)換,你要告訴編譯器對象的歸屬語義,不管對象是使用類型轉(zhuǎn)換(定義在objc/runtime.h)或Core Foundation樣式的宏(定義在NSObject.h)。
__bridge在Objective-C和Core Foundation間的指針轉(zhuǎn)換不附加對象的所有權(quán)。
__bridge_retained或 CFBridgingRetain將Objectiv-C指針轉(zhuǎn)換為Core Foundation指針,并且將對象的所有權(quán)轉(zhuǎn)給你。你負責調(diào)用CFRelease或相關(guān)的函數(shù)來放棄對象的所有權(quán)。
__bridge_transfer或 CFBridgingRelease將一個非Objective-C指針轉(zhuǎn)移到Objective-C指針,并將對象所有權(quán)轉(zhuǎn)交給ARC。ARC負責放棄對象的所有權(quán)。
例如,如果你有這樣的代碼:

  1. - (void)logFirstNameOfPerson:(ABRecordRef)person { 
  2.     NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); 
  3.     NSLog(@"Person's first name: %@", name); 
  4.     [name release]; 

你應該替代為:

  1. - (void)logFirstNameOfPerson:(ABRecordRef)person { 
  2.    
  3.     NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); 
  4.     NSLog(@"Person's first name: %@", name); 

【編譯器處理Cocoa方法返回的CF對象】(The Compiler Handles CF Objects Returned From Cocoa Methods)
編譯器了解Objective-C的那些沿用Cocoa命名規(guī)則返回Core Foundation類型的方法(參見 Advanced Memory Management Programming Guide)。例如,編譯器知道,在IOS中, UIColorCGColor方法返回的CGColor不會被擁有。你仍需使用合適的類型轉(zhuǎn)換,如下例所示:

  1. NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; 
  2. [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; 

【使用所有權(quán)關(guān)鍵字對函數(shù)參數(shù)進行強制類型轉(zhuǎn)換】(Cast Function Parameters Using Ownership Keywords)
函數(shù)調(diào)用中在Objective-C和Core Foundation對象之間進行轉(zhuǎn)換,你要告訴編譯器被傳入的對象的所有權(quán)語義。Core Foundation的所有權(quán)規(guī)則在Core Foundation的內(nèi)存管理規(guī)則中都已近說明了(參見 Memory Management Programming Guide for Core Foundation);Objective-C對象的規(guī)則在 Advanced Memory Management Programming Guide.有說明。
在下面的代碼片段中,傳入 CGGradientCreateWithColors函數(shù)的數(shù)組需要一個合適的類型轉(zhuǎn)換。 arrayWithObjects:方法返回的對象的所有權(quán)不會傳給函數(shù),因此需要用 __bridge轉(zhuǎn)換。

  1. NSArray *colors = <#An array of colors#>; 
  2. CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); 

以下方法實現(xiàn)中展示了代碼片段。要注意的是遵從Core Foundation內(nèi)存管理規(guī)則的Core Foundation內(nèi)存管理函數(shù)的用法。

  1. - (void)drawRect:(CGRect)rect { 
  2. 02      CGContextRef ctx = UIGraphicsGetCurrentContext(); 
  3. 03      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 
  4. 04      CGFloat locations[2] = {0.0, 1.0}; 
  5. 05      NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; 
  6. 06      [colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; 
  7. 07      CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); 
  8. CGColorSpaceRelease(colorSpace);  // Release owned Core Foundation object. 
  9. CGPoint startPoint = CGPointMake(0.0, 0.0); 
  10. CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds)); 
  11. CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, 
  12. kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); 
  13. CGGradientRelease(gradient);  // Release owned Core Foundation object. 

 

不要走開,下頁內(nèi)容更銷魂

#p#

【工程轉(zhuǎn)換時的常見問題】(Common Issues While Converting a Project)
當遷移已有工程時,可能你會遇到許多問題。這里列舉一些常見問題,以及解決辦法。
1.不能調(diào)用 retain, release,或 autorelease。
這是一個特殊點。你也不能寫:
while ([x retainCount]) { [x release]; }
2.不能調(diào)用 dealloc
如果你實現(xiàn)了一個單例對象或在init方法中替換一個對象,你通常會調(diào)用 dealloc方法。對于單例對象,使用共享實例模式。在 init方法中,你不再需要調(diào)用dealloc,因為對象在你重寫 self時會被釋放掉。
3.不能使用 NSAutoreleasePool對象
使用新的 @autoreleasepool{}結(jié)構(gòu)代替。這在你的自動釋放池中強制使用block結(jié)構(gòu),并且比 NSAutoreleasePool要快六倍。即使在非ARC的代碼中 @autoreleasepool也能工作,因為 @autoreleasepool較 NSAutoreleasePool要快得多,所以許多舊的”性能hacks“會無條件的被 @autoreleasepool所替代。
遷移器只處理 NSAutoreleasePool的簡單用法,不能處理復雜條件下的情況,或者一個定義在新的 @autoreleasepool結(jié)構(gòu)內(nèi)部的變量并在其之外使用的情況。
4.ACR需要你將在init方法中 [super init]的結(jié)果賦值給 self。
下面的代碼在ARC的init方法中是不合法的: 

  1. [super init]; 

簡單的修正是做如下變換 

  1. self = [super init]; 

更全面的改法是在繼續(xù)之前檢測結(jié)果是否為nil:

  1. self = [super init]; 
  2. if (self) { 
  3.    ... 

5.不能實現(xiàn)自定義的 retain和 release方法
實現(xiàn)自定義的 retain和 release方法會打破弱引用。有幾種常見原因是想要提供提供自定義實現(xiàn)的:
性能
請不要再這么做了; NSObject的 retain和 release現(xiàn)在更加快捷。如果你仍發(fā)現(xiàn)問題,請?zhí)峤籦ug。
實現(xiàn)自定義的弱指針系統(tǒng)
使用 __weak代替
實現(xiàn)單例類
使用共享示例代替。或使用類方法類替代實例方法,這避免了一直都要去分配對象空間的操作。
6."Assigned"實例變量成為了strong類型
在ARC之前,實例變量是非擁有引用(non-owning redernces)——直接將對象賦值給實例變量不會擴展對象的生命周期。為了令屬性成為強類型,你通常只要實現(xiàn)或合成訪問器方法,它們會調(diào)用合適的內(nèi) 存管理方法;相比較而言,你可能已經(jīng)如下例子中實現(xiàn)了訪問器方法來維護一個弱類型屬性。

  1.     @interface MyClass : Superclass { 
  2.     id thing; // Weak reference. 
  3. // ... 
  4. @end 
  5. @implementation MyClass 
  6. - (id)thing { 
  7.     return thing; 
  8. - (void)setThing:(id)newThing { 
  9.     thing = newThing; 
  10. // ... 
  11. @end 

使用ARC,實例變量默認是強類型引用——將實例變量直接賦值給對象的確會擴展對象的生命周期。遷移工具沒辦法決定實例變量何時應該是 weak類型的。為了像之前那樣維護同樣的行為,你必須將實例變量標記為 weak類型,或使用一個聲明式屬性。

  1. @interface MyClass : Superclass { 
  2.     id __weak thing; 
  3. // ... 
  4. @end 
  5. @implementation MyClass 
  6. - (id)thing { 
  7.     return thing; 
  8. - (void)setThing:(id)newThing { 
  9.     thing = newThing; 
  10. // ... 
  11. @end 
  12. 或 
  13. @interface MyClass : Superclass 
  14. @property (weak) id thing; 
  15. // ... 
  16. @end 
  17. @implementation MyClass 
  18. @synthesize thing; 
  19. // ... 
  20. @end 

7.在C語言結(jié)構(gòu)體重不能使用強類型的ids,例如,以下代碼會編譯不過

  1. struct X { id x; float y; }; 

因為x默認肯定是被保留的,編譯器無法安全的合成所有保證代碼正常運轉(zhuǎn)所需的所有代碼。例如,如果你通過一些最終會被釋放的代碼來傳入一個指針到這些結(jié)構(gòu) 體后,每個id在結(jié)構(gòu)體回收之前會被被迫釋放掉。編譯器不能可靠的做到這點,所以在結(jié)構(gòu)體中的強類型的ids在ARC模式下是完全無效的。以下有幾個可能 的解決辦法:
(1)使用Objective-C對象代替結(jié)構(gòu)體
這是***的實踐方法。
(2)如果使用Objective-C對象是次優(yōu)方案,(可能你想要這些結(jié)構(gòu)體組成的一個數(shù)組)那么考慮void *進行替代。
這需要使用顯示的類型轉(zhuǎn)換,在下面會提到。
(3)將對象引用標記為__unsafe_unretained
該方法對于一些不常見的模式可能會有效,如下:

  1. struct x { NSString *S;  int X; } StaticArray[] = { 
  2.        @"foo", 42, 
  3.        @"bar, 97, 
  4.          ... 
  5. }; 

這可能存在問題,并且如果對象在指針之外會被釋放掉,這是不安全的,但實際對于像字符串常量一樣一直存在的東西來說確實很有用的。
8.不能在 id與 void *(包括Core Foundation類型)之間進行直接轉(zhuǎn)換
“Managing Toll-Free Bridging.”中由詳細的描述。
【常見問題】(Frequently Asked Questions)      
我該怎樣理解ARC?它把retians/releases放在哪里呢?
嘗試不要再考慮retain/release應該放在哪,要考慮你應用的邏輯。考慮你對象中的”strong和weak“指針,對象的所有權(quán),可能的循環(huán)引用。
我是否還需要為我的對象編寫dealloc方法?
可能需要。
因為ARC不會自動操作malloc/free,Core Foundation對象的生命周期管理,文件描述,等等。你仍需要在dealloc方法中是否這樣的資源。
你不需要(實際根本不需要)釋放實例變量,但是你需要在系統(tǒng)類和其它未使用ARC編譯的代碼上調(diào)用[self setDelegate:nil]。
ARC中的dealloc方法不需要或不允許調(diào)用[super dealloc];到super的鏈式結(jié)構(gòu)是在運行期進行處理和實施的。
在ARC中仍存在循環(huán)引用嗎?
是的。
ARC自動處理retain/release,并且繼承了循環(huán)引用的問題。幸運的是,遷移到ARC的代碼很少內(nèi)存泄露,因為屬性(property)已經(jīng)聲明了是否要保留。
在ARC下我能創(chuàng)建C數(shù)組的保留指針不?
是的,可以!

  1. // Note calloc() to get zero-filled memory. 
  2. __strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(sizeof(SomeClass *), entries); 
  3. for (int i = 0; i < entries; i++) { 
  4.      dynamicArray[i] = [[SomeClass alloc] init]; 
  5. // When you're done, set each entry to nil to tell ARC to release the object. 
  6. for (int i = 0; i < entries; i++) { 
  7.      dynamicArray[i] = nil; 
  8. free(dynamicArray); 

有些其它需要注意的地方:
某些情況下你需要使用__strong SomeClass **,因為默認是__autoreleasing SomeClass **.
分配的內(nèi)存必須是零填充的
你必須在釋放數(shù)組(memset或bzero無法工作)之前將每個元素設置為nil.
避免使用memcpy或realloc
ARC運行速度會慢嗎?
這取決于你的測量方式,但基本”很快“。編譯器高效的消除許多外部的 retian和 release調(diào)用,而且總的來說會更加關(guān)注于提升Objective-C運行時的速度。尤其是,當調(diào)用者是ARC代碼時,常用的"返回一個 retain/autoreleased對象"模式會更快速而且實際上并沒有將對象放入到自動釋放池中。
我可以在特定文件下退出ARC嗎?
可以。
在你遷移工程來使用ARC時,-fobjc-arc編譯器標記默認會設置到每個Objective-C的源文件。你可以使用 -fno-objc-arc編譯器標記來在特定的類中禁用ARC。在Xcode中,在target的 Build Phases中,打開 Compile Sources 組顯示源文件列表。雙擊你想要設置標記的文件,在pop-up面板中輸入-fno-objc-arc指定,之后點擊完成。

Apple Doc

責任編輯:閆佳明 來源: oschina
相關(guān)推薦

2024-06-25 08:18:55

2017-07-20 16:55:56

Android事件響應View源碼分析

2020-10-09 08:15:11

JsBridge

2025-01-26 15:38:11

Spring事務編程式

2024-05-17 10:05:06

Java機制應用

2021-04-07 13:28:21

函數(shù)程序員異步

2019-07-23 08:55:46

Base64編碼底層

2015-07-15 17:09:48

HiveHadoop分布式文件系統(tǒng)

2022-02-21 09:44:45

Git開源分布式

2021-06-30 00:20:12

Hangfire.NET平臺

2019-04-17 15:16:00

Sparkshuffle算法

2023-05-12 08:19:12

Netty程序框架

2021-04-09 08:40:51

網(wǎng)絡保險網(wǎng)絡安全網(wǎng)絡風險

2017-09-05 08:52:37

Git程序員命令

2024-05-10 08:19:59

arthasjava字節(jié)碼

2025-03-07 08:24:10

Javavolatilecount++

2021-05-15 09:18:04

Python進程

2021-07-01 10:01:16

JavaLinkedList集合

2020-10-22 08:25:22

JavaScript運作原理

2021-02-02 18:39:05

JavaScript
點贊
收藏

51CTO技術(shù)棧公眾號

久久久久中文字幕2018| 欧美视频在线一区| 国产精品免费看一区二区三区| 久久一二三四区| 色狼人综合干| 欧美精品v日韩精品v韩国精品v| 天天想你在线观看完整版电影免费| 欧美一区二区三区黄片| 免费久久精品视频| 欧美精品www在线观看| 国产高清一区二区三区四区| 韩国三级成人在线| 欧美日韩国产一中文字不卡| 亚洲国产精品一区二区第四页av| 丰满人妻熟女aⅴ一区| 视频一区国产视频| 欧美黄色免费网站| av网在线播放| 成人搞黄视频| 4438x成人网最大色成网站| 免费特级黄色片| 91在线播放网站| 成人免费的视频| 成人美女免费网站视频| 国产又黄又粗又爽| 中文字幕免费一区二区| 一区二区三区视频免费| 完美搭档在线观看| 欧美成年网站| 欧美日韩在线亚洲一区蜜芽| 成年人视频观看| 在线视频中文字幕第一页| 国产精品水嫩水嫩| 欧美一区二区三区在线播放| 成人免费视频国产| 国产一区二区三区久久久 | 欧美人与性动交α欧美精品济南到 | 7777精品伊久久久大香线蕉语言| 这里只有精品国产| 久久国产精品毛片| 5278欧美一区二区三区| 久久伊人成人网| 亚洲最大黄网| 久久久国产精彩视频美女艺术照福利| 五月天精品视频| 日韩美女毛片| 亚洲精品成人久久电影| 精品人妻伦一二三区久| 日韩欧美另类中文字幕| 91精品在线一区二区| 婷婷免费在线观看| 久久精品97| 欧美精品一二三区| www.se五月| 亚洲欧美在线人成swag| 欧美老女人第四色| 99中文字幕在线| 狂野欧美xxxx韩国少妇| 日韩午夜三级在线| 亚洲精品乱码久久久久久9色| 91精品网站在线观看| 欧美精品九九99久久| 在线观看免费不卡av| 亚洲视频资源| 日韩欧美国产三级电影视频| 欧美熟妇精品一区二区| 成人免费在线电影网| 亚洲第一网站男人都懂| 一女三黑人理论片在线| 久久综合色占| 在线观看日韩www视频免费| 制服丨自拍丨欧美丨动漫丨| 97久久夜色精品国产| 久久韩国免费视频| 久久久国产精品黄毛片| 亚洲精品色图| 国产成人福利网站| 一区二区视频网| 国产精品自拍三区| 精品国产综合久久| 丁香婷婷在线观看| 日韩毛片高清在线播放| 精品人妻人人做人人爽| 涩涩av在线| 欧美日韩国产首页| 日本精品一二三区| 国产剧情一区| 久久影视电视剧免费网站清宫辞电视| 日韩精品一区二区av| 六月天综合网| 亚洲已满18点击进入在线看片| 日韩有码第一页| 国产色产综合色产在线视频| avove在线观看| 欧美日韩国产观看视频| 欧美日韩免费在线视频| 97人妻精品一区二区三区免费| 久久av免费| 久久91精品国产91久久久| 久久久成人免费视频| 极品少妇xxxx精品少妇| 久久久精品有限公司| 成人片在线看| 日韩欧美在线中文字幕| 欧美体内she精高潮| 综合亚洲自拍| 欧美激情第三页| 亚洲婷婷久久综合| 成人av免费观看| 一区二区成人国产精品| 日韩伦理精品| 日韩丝袜情趣美女图片| 国产又粗又猛又爽视频| 欧美精选一区| 国产在线拍偷自揄拍精品| 少妇av一区二区| 亚洲人成亚洲人成在线观看图片| 国产精品视频一区二区三区四区五区| 精品国产鲁一鲁****| 一区二区欧美在线| 国产精品视频123| 成人精品免费视频| 久久久久亚洲av无码专区喷水| 日本成人片在线| 亚洲精品久久久久中文字幕二区 | 美国黄色一级视频| 小说区亚洲自拍另类图片专区| 欧洲成人性视频| 蜜桃av鲁一鲁一鲁一鲁俄罗斯的| 亚洲视频图片小说| 午夜国产一区二区三区| 一区二区三区视频免费观看| 午夜美女久久久久爽久久| 亚洲成人77777| 亚洲三级在线免费观看| 自拍偷拍一区二区三区四区| 精品国产aⅴ| 国产成人精品久久二区二区| 欧美视频综合| 黑人巨大精品欧美一区二区| 亚洲一区二区在线免费| 亚洲天堂黄色| 国产伦理一区二区三区| 麻豆福利在线观看| 91精品国产欧美一区二区| 黄色av片三级三级三级免费看| 日日摸夜夜添夜夜添精品视频 | 少妇欧美激情一区二区三区| 欧美大黑bbbbbbbbb在线| 国产狼人综合免费视频| 在线国产情侣| 欧美日本一区二区| 国产wwwwxxxx| 国内成人自拍视频| 韩国黄色一级大片| 精品国产一区二| 久久999免费视频| 国产综合视频在线| 天天影视涩香欲综合网 | 国产亚洲一区二区三区不卡| 国产91免费观看| av网在线观看| 在线成人小视频| wwwav国产| 国产不卡高清在线观看视频| 国产欧美日韩网站| 九九视频免费观看视频精品| 国产精品久久久久久网站| 欧美一区二区三区| 日韩一级片网址| 日韩欧美中文字幕一区二区| 91美女在线视频| 亚洲五月天综合| 亚洲色图欧美| 狠狠色伊人亚洲综合网站色| 日韩欧美一区二区三区在线观看 | 黄色一级片中国| 99精品欧美一区| 邪恶网站在线观看| 欧美一区91| 久热国产精品视频一区二区三区| gogo亚洲高清大胆美女人体| 久久精品亚洲热| 欧美视频一二区| 欧美系列亚洲系列| 免费视频网站www| 久久婷婷综合激情| 日本高清一区二区视频| 亚洲福利免费| 一区二区三区欧美成人| 豆花视频一区二区| 国产精品美女免费看| 女同一区二区免费aⅴ| 亚洲天堂久久av| 亚洲av无码国产综合专区| 一本久久综合亚洲鲁鲁五月天| 91免费公开视频| 久久日韩精品一区二区五区| 91精品999| 亚洲欧美日韩国产一区| 妞干网这里只有精品| 亚洲+小说+欧美+激情+另类| 亚洲专区中文字幕| 忘忧草在线www成人影院| 欧美日韩成人在线观看| 成人综合影院| 亚洲精品福利在线观看| 国产特黄一级片| 欧洲av一区二区嗯嗯嗯啊| 久久免费视频精品| 亚洲欧洲日韩女同| 免费看黄色的视频| 成人av动漫在线| 五月六月丁香婷婷| 日本中文字幕一区| 香港三级韩国三级日本三级| 亚洲乱码电影| 亚洲欧洲一区二区福利| 偷窥自拍亚洲色图精选| 成人av资源网| 精品欧美视频| 成人免费黄色网| 成人四虎影院| 国产精品久久久久久av福利软件| 成人黄色动漫| 久久久久久12| 欧美aaaaaaa| 欧美成人性色生活仑片| 免费在线视频欧美| 在线日韩欧美视频| 久草福利在线| 亚洲欧美综合区自拍另类| 免费国产精品视频| 精品欧美一区二区久久| 国产国语亲子伦亲子| 91精品黄色片免费大全| 国产情侣激情自拍| 欧美福利视频一区| 91精品国自产| 欧美精品乱码久久久久久按摩| 中文字幕精品无码亚| 在线视频观看一区| 国产精品51麻豆cm传媒 | 性欧美1819| 久草在线在线精品观看| 手机看片福利日韩| 免费在线看一区| 爱情岛论坛亚洲首页入口章节| 久久亚洲不卡| 黄色成人免费看| 免费观看日韩av| 亚洲 国产 图片| 国产精品中文有码| 绯色av蜜臀vs少妇| 成人久久18免费网站麻豆| av av在线| 久久一二三国产| 亚洲色图第四色| 亚洲欧洲日韩在线| 欧美日韩激情在线观看| 一级精品视频在线观看宜春院| 国产亚洲小视频| 欧美日韩色婷婷| 黄色污污网站在线观看| 精品视频123区在线观看| 国产日本精品视频| 亚洲精品一区二区三区精华液| 香港一级纯黄大片| 中国china体内裑精亚洲片| 日韩理伦片在线| 欧美精品videosex性欧美| 无遮挡爽大片在线观看视频| 国产精品福利观看| 2019中文亚洲字幕| 粉嫩av四季av绯色av第一区| 网曝91综合精品门事件在线| 性欧美精品一区二区三区在线播放 | 亚洲黄色片网站| 国产黄色免费在线观看| 久久在线精品视频| 蜜桃视频www网站在线观看| 国产精品久久久久久久久久久久久| 96sao精品免费视频观看| 国产一区不卡在线观看| 三区四区不卡| 人体内射精一区二区三区| 奇米四色…亚洲| 亚洲欧美综合视频| 欧美国产禁国产网站cc| 国产在线观看免费av| 欧美视频在线观看一区二区| www.com欧美| 国产一区二区美女视频| 午夜激情在线| 国产精品影院在线观看| 九九热播视频在线精品6| 综合网五月天| 先锋a资源在线看亚洲| 久久精品一卡二卡| 久久新电视剧免费观看| 激情综合网五月天| 欧美三区免费完整视频在线观看| 欧美一级一区二区三区| 久久精品国产2020观看福利| 小h片在线观看| 99精品99久久久久久宅男| 日韩成人激情| 男人的天堂99| 国产a久久麻豆| 亚洲欧洲综合网| 在线观看av一区二区| 色欲av永久无码精品无码蜜桃| 欧美成aaa人片免费看| 国产成人毛片| 日本午夜精品一区二区三区| 日韩图片一区| 中文字幕一区二区三区人妻在线视频| 国产精品久久影院| 欧美日韩一级黄色片| 日韩经典中文字幕| 男女羞羞视频在线观看| 亚洲综合中文字幕68页| 久久免费大视频| 日本久久久久久久久久久久| 久久伊人蜜桃av一区二区| 国产午夜视频在线| 日韩午夜av电影| av网址在线免费观看| 成人黄色免费网站在线观看| 国产一区二区精品福利地址| 男人操女人免费软件| 不卡一卡二卡三乱码免费网站| 国产在线免费视频| 欧美变态tickle挠乳网站| aaa大片在线观看| 3d动漫精品啪啪一区二区三区免费| 色婷婷亚洲mv天堂mv在影片| 天天操天天摸天天爽| 国产亚洲午夜高清国产拍精品| 中文字字幕在线中文| 亚洲精品中文字幕av| 色在线中文字幕| 欧美日韩精品中文字幕一区二区| 亚洲一区观看| 国产精品jizz| 一本色道久久综合亚洲91| 国家队第一季免费高清在线观看| 国产成人一区二| 青青草国产免费一区二区下载| 性欧美1819| 亚洲精品久久7777| wwwav网站| 午夜精品久久久久久99热| 午夜先锋成人动漫在线| 日本www高清视频| 国产精品久久夜| www.天堂在线| 国外成人在线直播| 最新国产一区| 成人日韩在线视频| 一区二区欧美视频| 午夜视频在线播放| 国产精品电影在线观看| 9999国产精品| 亚洲图片欧美另类| 欧美性xxxx| 日本在线观看www| 97视频资源在线观看| 亚洲精品三级| www.99热| 日韩视频国产视频| 三妻四妾完整版在线观看电视剧| 日本不卡在线观看| 久草热8精品视频在线观看| 久久99久久98精品免观看软件| 日韩精品在线播放| 成人午夜在线| 久艹在线免费观看| 国产欧美日韩视频在线观看| aaa一区二区| 日本精品久久久久影院| 国产精品99久久久久久动医院| 亚洲免费观看在线| 91福利在线免费观看| 成人免费看片| 免费成人看片网址| 经典一区二区三区| 日本三级一区二区| 久久精品一本久久99精品| 日韩a级大片| 日本77777| 色婷婷亚洲综合| 综合图区亚洲| 日韩片电影在线免费观看| 国产精品一区二区在线看| 无码人妻aⅴ一区二区三区有奶水| 两个人的视频www国产精品| 色天下一区二区三区| 国产无套精品一区二区三区| 欧美中文字幕亚洲一区二区va在线|