精品欧美一区二区三区在线观看 _久久久久国色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ù)棧公眾號

久久福利视频网| 亚洲国产精品久久艾草纯爱| 国产精品久久久久av| 一级片黄色录像| 久久的色偷偷| 偷拍日韩校园综合在线| 日本一区二区免费看| 国产精品视频第一页| 亚洲人成高清| 中文字幕在线视频日韩| 欧洲成人午夜精品无码区久久| 欧美少妇网站| 国产精品嫩草久久久久| 4444kk亚洲人成电影在线| 中文字幕亚洲高清| 国产精品久久久久无码av| 精品免费国产二区三区| 婷婷六月天在线| 国产丝袜精品丝袜| 久久九九全国免费| 动漫3d精品一区二区三区 | 精品久久综合| 精品嫩草影院久久| 日韩va在线观看| 天天综合网站| 午夜精品免费在线观看| 手机福利在线视频| 国产三级视频在线| 成人国产免费视频| 亚洲va久久久噜噜噜久久天堂| 国产免费一区二区三区四区五区| 亚洲激情综合| 欧美人在线观看| 我要看一级黄色录像| 精品国产乱码久久久久久1区2匹| 亚洲国模精品私拍| 在线观看一区二区三区视频| 亚洲ww精品| 欧美午夜不卡在线观看免费| 欧美成人免费高清视频| 美女高潮在线观看| 午夜激情一区二区| 亚洲精品蜜桃久久久久久| av免费在线免费观看| 中文字幕一区视频| 日韩资源av在线| 欧美日韩免费做爰大片| 久久综合色天天久久综合图片| 岛国视频一区免费观看| 女人18毛片水真多18精品| 国产乱人伦精品一区二区在线观看| 国产免费一区视频观看免费| 久久国产香蕉视频| 免费成人在线网站| 国产精品色午夜在线观看| 欧美日韩 一区二区三区| 日日嗨av一区二区三区四区| 国产精品成人一区二区三区吃奶| 波多野结衣绝顶大高潮| 日韩av中文字幕一区二区| 国产精品久久久久久久美男| 一卡二卡在线观看| 黄色精品一二区| 1卡2卡3卡精品视频| 亚洲黄色片视频| a在线播放不卡| 久久久水蜜桃| 北岛玲日韩精品一区二区三区| 中文字幕欧美国产| 黄频视频在线观看| a级网站在线播放| 一区二区三区91| 鲁一鲁一鲁一鲁一色| 电影一区二区三| 在线观看区一区二| 欧美特黄aaa| 视频在线亚洲| 亚洲乱码国产乱码精品精| 日韩中文字幕有码| 在线一区免费| 7777kkkk成人观看| 中文字幕乱码人妻无码久久 | 人妻精油按摩bd高清中文字幕| 一区视频网站| 日韩精品中文字幕在线| 网爆门在线观看| 欧美日韩一区二区高清| 欧洲一区二区视频| 国产精品毛片一区视频播| 成av人片一区二区| 色女孩综合网| 丰满大乳少妇在线观看网站| 91福利精品第一导航| 欧美体内she精高潮| 日韩极品少妇| 日韩在线欧美在线国产在线| 国产精品成人aaaa在线| 奇米影视在线99精品| 国产精品国产亚洲精品看不卡15| 国产高清美女一级毛片久久| 亚洲综合成人在线| 欧美日韩大尺度| 中文字幕视频精品一区二区三区| 亚洲人成绝费网站色www| 人妻少妇精品一区二区三区| 久久一区中文字幕| 国产高清一区二区三区| 色欧美激情视频在线| 精品久久久久久中文字幕| 久久6免费视频| 亚洲深夜福利在线观看| 欧美国产日产韩国视频| 亚洲视频久久久| 91美女视频网站| 日韩国产小视频| 91精品店在线| 亚洲欧美日韩国产中文| 久久久久久激情| 九九九久久久精品| 欧美一区二区三区在线播放| а√在线天堂官网| 91精品麻豆日日躁夜夜躁| 中文字幕第4页| 一本久道综合久久精品| 亚洲自拍欧美色图| 日本在线免费网| 欧美亚洲综合一区| 麻豆精品免费视频| 国产精品老牛| 国产成人成网站在线播放青青| 免费不卡视频| 欧美日韩综合一区| 影音先锋男人在线| 日日摸夜夜添夜夜添精品视频| 久久精品二区| 神马午夜在线视频| 日韩国产精品视频| 亚洲精品国产精品乱码| 9色porny自拍视频一区二区| 国产欧美精品aaaaaa片| 日韩一区二区三区精品| 久久中文字幕国产| 97精品人妻一区二区三区在线| 久久蜜臀精品av| 男人的天堂99| 嫩草一区二区三区| 国产福利视频一区| 东热在线免费视频| 欧美三级视频在线| 2017亚洲天堂| 精品无码三级在线观看视频| youjizz.com亚洲| 精品国产三级| 色综合久久精品亚洲国产 | 国产精品日本一区二区三区在线| x99av成人免费| 国产精品久久综合青草亚洲AV| 中文字幕亚洲在| 三日本三级少妇三级99| 女人天堂亚洲aⅴ在线观看| 91在线无精精品一区二区| 97caopor国产在线视频| 亚洲二区在线播放视频| 日韩不卡视频在线| 国产婷婷色一区二区三区四区 | 久久麻豆视频| 久久精品视频播放| 丰满肉肉bbwwbbww| 午夜成人在线视频| 国产一二三四五区| 久久精品国产精品青草| 毛片av在线播放| 欧美日韩精品一区二区三区在线观看| 日本精品性网站在线观看| 国产精品一区在线看| 欧美日韩aaaaaa| 麻豆成人在线视频| 久久夜色精品国产噜噜av| 成人免费在线观看视频网站| 欧美aⅴ99久久黑人专区| 精品久久久久久一区二区里番| 超碰超碰人人人人精品| www.日韩视频| 天堂国产一区二区三区| 欧美日韩一区二区三区在线| 九九热只有精品| 久久久久国产精品麻豆ai换脸 | 色综合天天综合网国产成人网| 亚洲色偷精品一区二区三区| 欧美四级电影网| 久一视频在线观看| 国产欧美精品一区二区色综合 | 国产成人aa在线观看网站站| 日本精品免费观看| 亚洲综合伊人久久大杳蕉| 亚洲女人天堂成人av在线| 国产露脸91国语对白| 色综合久久99| 欧美高清视频一区二区三区| 久久久久久久久久电影| 国产精品二区视频| 免费成人在线视频观看| 日韩欧美国产综合在线| 久久久久久久久久久久久久久久久久| 精品欧美一区二区精品久久| 亚洲一区二区av| 欧美综合在线观看| 污影院在线观看| 中文字幕日韩欧美在线| 午夜福利一区二区三区| 欧美一区二区三区男人的天堂| 亚洲 欧美 中文字幕| 亚洲国产视频网站| 性生交大片免费全黄| 久久无码av三级| 久久人妻少妇嫩草av蜜桃| 精品综合免费视频观看| 国产精品69页| 国产精品腿扒开做爽爽爽挤奶网站| 国产树林野战在线播放| 久久国产综合| 欧美日韩亚洲免费| 欧美人妖在线观看| 国产精品视频一区二区三区经| 中文字幕日本一区| 国产精品一区久久| 欧美aaa视频| 欧洲永久精品大片ww免费漫画| 操人在线观看| 久久久之久亚州精品露出| 97caopron在线视频| 久久av在线看| 高清全集视频免费在线| 日韩视频精品在线| 欧美性videos| 日韩在线观看免费高清| 三区四区电影在线观看| 日韩中文字幕在线免费观看| eeuss影院在线观看| 一区二区三区四区精品| 伦理片一区二区三区| 亚洲男女自偷自拍图片另类| 欧美日韩在线精品一区二区三区激情综| 亚洲成人黄色网址| 污污的视频网站在线观看| 精品国产成人系列| 黑人精品一区二区| 欧美精品一区二区三区蜜桃| 日本wwwxxxx| 亚洲国产毛片完整版| 高清国产mv在线观看| 精品国产伦一区二区三区观看方式 | 激情开心成人网| 国产mv免费观看入口亚洲| 男人皇宫亚洲男人2020| 国产成一区二区| 日韩精品一区二区三区av| 国产精品三级久久久久久电影| 日韩美女在线| 91九色视频在线| 一区二区三区视频免费视频观看网站| 粉嫩av一区二区三区免费观看 | 久久久久亚洲av成人毛片韩| 色综合久久综合网97色综合| 日韩在线视频不卡| 欧美日韩一级片网站| av网站免费大全| 亚洲第一中文字幕| 精品美女视频在线观看免费软件| 中文字幕九色91在线| www免费视频观看在线| 欧美福利视频在线| 在线免费看h| 国产精品专区第二| 亚洲超碰在线观看| 久热国产精品视频一区二区三区| 日韩精品2区| 屁屁影院ccyy国产第一页| 亚洲欧美日韩国产一区| 91插插插插插插插插| 国产99久久久国产精品潘金网站| 国产制服丝袜在线| 国产精品另类一区| 久久久久久久极品内射| 色94色欧美sute亚洲线路二| 国产理论片在线观看| 精品中文视频在线| 国产精品刘玥久久一区| 国产91久久婷婷一区二区| 亚洲综合视频| 久久人人97超碰人人澡爱香蕉| 日韩欧美网站| 欧美综合在线播放| 精久久久久久久久久久| 懂色av粉嫩av蜜乳av| 亚洲美女屁股眼交| 亚洲天堂男人av| 日韩欧美国产精品一区| 成年人在线观看网站| 欧美激情一区二区三级高清视频 | 欧美一级黄色录像| 噜噜噜噜噜在线视频| 久久91精品国产91久久久| 精品无人乱码一区二区三区| 国产欧美日韩综合精品二区| 91综合在线| 欧美aⅴ在线观看| 国产成人精品一区二区三区网站观看| 美女爆乳18禁www久久久久久| 午夜伊人狠狠久久| 国产视频手机在线| 国产亚洲精品久久久| jizz欧美激情18| 一级片视频网站| 好吊妞视频这里有精品| 国产日本欧美一区二区| 午夜精品在线观看| 亚欧洲乱码视频| 夜色77av精品影院| 亚洲性av网站| 亚洲精品免费一区亚洲精品免费精品一区| 亚洲 欧美 激情 小说 另类| 久久久久久久久久久久久久| 欧美年轻男男videosbes| 亚洲精品在线观看视频| 999精品网站| 在线中文字幕-区二区三区四区| 奇米777欧美一区二区| 精品少妇一区二区三区视频免付费| 水蜜桃一区二区三区| 日韩在线视频不卡| 久久的色偷偷| 亚洲欧美自拍偷拍| 成人av影视在线| 日韩成人短视频| 日韩精品中文字幕吗一区二区| 亚洲综合偷拍欧美一区色| 91免费欧美精品| 国产一级特黄视频| 亚洲精品蜜桃乱晃| 欧美在线观看一二区| 亚洲人成网站在线观看播放| 国产成人精品a视频| 91精品二区| 亚洲国产高清自拍| 无码粉嫩虎白一线天在线观看 | 国产精品国产三级国产专播精品人| 在线免费看黄色片| 在线看的毛片| 中文字幕亚洲一区二区va在线| 久久精品国产理论片免费| 99热在线观看免费精品| 91九色鹿精品国产综合久久香蕉| 日韩欧美高清视频| 青娱乐一区二区| 日韩精品免费专区| 国产日产欧美精品一区二区三区| 5566日本婷婷色中文字幕97| 亚洲色图第四色| 国产精品美女久久久久| 欧美日韩国产精品一区| 开心色怡人综合网站| 国产欧美久久久| 国产做a爰片久久毛片| 国产69久久精品成人| 中文字幕av免费在线观看| 色综合综合色| 亚洲精品国偷自产在线99热| 久久久久久国产精品日本| caoporn-草棚在线视频最| 亚洲欧美日韩系列| 日韩欧美在线观看强乱免费| 3p视频在线观看| 久久久www免费人成精品| 欧美激情一区二区三区在线视频| 97超碰国产在线| 国产精品v日韩精品v欧美精品网站 | 免费国产在线视频| 国产亚洲精品bt天堂精选| 国产乱国产乱老熟300| 亚洲成人激情图| 欧美舌奴丨vk视频| 国产福利片一区二区| jvid福利写真一区二区三区| 久久久999久久久| 色综合久久88| 国产探花在线精品一区二区| 亚洲午夜激情影院| 午夜视黄欧洲亚洲| 成av人电影在线观看| www.久久艹| 久久在线精品| 欧美成人三级视频| 亚洲欧美激情视频| 国产美女视频一区二区| 日韩人妻精品无码一区二区三区| 亚洲欧洲99久久| 欧美一区二区视频| 91久久精品一区二区别| 日韩电影在线看|