成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一篇文章徹底弄清ARC始末

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

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

摘要(Summary)

通過在編譯期添加代碼的方式,ARC保證所有對象按需存在,按需釋放。從概念上來講,它與手動引用計數(參見 Advanced Memory Management Programming Guide)有著相同的內存管理約定,二者都會為你添加合適的內存管理方法調用。 為了編譯器能生成正確的代碼,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轉換過程中需要手工操作的部分(例如刪除retain和release方法調用),并且幫助你在 遷移過程中不能自動完成的操作(選擇Edit->Refactor->Convert to Objective-C ARC)。遷移工具將工程中的所有文件使用ARC進行轉換。如果你覺得在某些文件中使用手動引用計數會更方便,那么你也可以選擇在單獨文件中使用ARC。
參見:
Advanced Memory Management Programming Guide
Memory Management Programming Guide for Core Foundation

ARC概述(ARC Overview)

ARC會評估對象所需的生命期,并會在編譯期為你自動插入合適的內存管理調用方法,取代之前你不得不考慮何時需要使用 retain, release以及 autorelease的操作方式。編譯器也會為你生成合適的 dealloc方法??偟膩碚f,如果你僅使用ARC,傳統的Cocoa命名規范只會在你需要與使用手動引用計數的代碼交互時才是重要的。一個完整正確的Person類的實現看起來可能是這樣的:

  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,你可以如下實現一個 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會維護內存管理,所以 Person和 NSNumber對象都不會泄露。
你也可以安全的實現 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強制執行新規則】(ARC Enforces New Rules)
為了正常運轉,ARC使用了一些在使用其它編譯模式下沒有的新規則。這些規則意在提供完全可靠的內存管理模型;在某些情況下,它們僅使用***實踐方法,在其它情況下,它們僅簡化你的代碼或明顯的做出推論告知你不需要處理內存管理。如果
你違反了這些規則,你會馬上得到一個編譯期錯誤,而不是在運行期可能會顯現的一個狡猾的bug。
1.不能顯示的調用dealloc,實現或調用 retain, release, retainCount,或 autorelease。
同樣也不要能使用 @selector(retain), @selector(release), 等等類似的選擇器。
如果你需要管理資源而不是釋放實例變量,那你可以實現 dealloc方法。你不需要(事實上你不能)釋放實例變量,但你可能需要在系統類和其它的未使用ARC代碼中調用 [systemClassInstance setDelegate:nil] 方法。
在ARC中自定義的 dealloc方法不要調用 [super dealloc]方法(它實際上會導致編譯器錯誤)。到super的鏈式調用是自動的并且是編譯器強制執行的。
你仍可以在Core Foundation樣式的的對象上,使用 CFRetain, CFRelease,和其它相關的函數。
2.你不能使用 NSAllocateObject 或 NSDeallocateObject
你使用 alloc來創建對象;運行時系統會注意釋放這些對象。
3.你不能在C語言結構體中使用對象指針。 與其使用一個結構體( struct),不如創建一個Objective-C類來管理數據。
4. id與 void*之間不能隨意轉換
你必須使用特定的類型轉換來告訴編譯器對象的生命周期。你需要在Objective-C對象和以函數參數傳入的Core Foundation類型值之間進行這樣的轉換。有關詳情,參見 “Managing Toll-Free Bridging”
5.你不能使用 NSAutoreleasePool對象
ARC 提供了 @autoreleasepool來代替。這比 NSAutoreleasePool更高效。
6.你不能使用內存區(memory zones)。
再也沒有使用 NSZone的必要了——現代的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)。弱類型應用不會延長它所指向對象的生命周期,一旦對象沒有強引用指向對象時,弱引用會自動變為 nil
在程序中,你應該充分利用這些限定符來管理對象圖。尤其是,ARC不能阻止強引用循環(strong reference cycles,之前稱為retain cycles,參見“Practical Memory Management”)的發生。審慎的使用弱類型關系會幫助你避免創建強引用循環。
【Property的屬性】(Property Attributes)
weak和 strong關鍵字是新引入的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指定一個引用,該引用不會維持所持對象的生命期,并且在沒有強引用指向對象時也不會設置為nil。如果它所指向的對象已經被釋放,那么它會成為一個野指針。
__autoreleasing 用以指示以引用(id*)傳入的參數并在retun后自動釋放。
你應該正確的修飾變量。在對象變量的聲明時使用限定符的正確格式為:

  1. ClassName * qualifier variableName; 

例如:

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

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

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

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

  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)和參數( __autoreleasing)之間的區別導致編譯器創建臨時變量。在獲取__strong變量的地址時你可以通過將參數聲明為 id __storng*來獲得其原始指針。或者你可以將變量聲明為 __autoreleasing。


不要走開,下頁內容更勁爆

#p#

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

  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變量。以下代碼列舉了一個簡單的實現:

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

而對于特殊的循環,你應該使用:

  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。但這也不適用于特殊的循環,因為在實際問題中驗證 __unsafe_unretained指針是否仍有效或是否仍指向相同的對象,是非常困難或根本不可能實現的。
【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. 

這個簡單的結構讓編譯器來判斷引用計數的狀態。在入口,自動釋放池會被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的模式已經發生變化,并且在跨平臺下保持一致性。你通常應該接受的是:outlets應該是 weak的,除了那些在nib文件(或storyboard屏)中File‘s Owner指向的***對象應該是 strong的。
Resource Programming Guide.中的 ”Nib Files“做出了全面的解釋。
【堆變量會初始化為nil】(Stack Variables Are Initialized with nil)
使用ARC,strong,weak,以及autoreleasing的堆變量現在會隱式的初始化為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。如果在某些文件中使用手動引用技術對你來說更方便些,你可以選擇在單獨的文件上使用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對象的生命周期;你必須調用符合Core Founda內存管理規則的CFRetain和CFRelease方法(或者合適的特殊類型變體)來釋放對象。(參見 Memory Management Programming Guide for Core Foundation
如果你在Objective-C對象和Core Foundation樣式對象間執行類型轉換,你要告訴編譯器對象的歸屬語義,不管對象是使用類型轉換(定義在objc/runtime.h)或Core Foundation樣式的宏(定義在NSObject.h)。
__bridge在Objective-C和Core Foundation間的指針轉換不附加對象的所有權。
__bridge_retained或 CFBridgingRetain將Objectiv-C指針轉換為Core Foundation指針,并且將對象的所有權轉給你。你負責調用CFRelease或相關的函數來放棄對象的所有權。
__bridge_transfer或 CFBridgingRelease將一個非Objective-C指針轉移到Objective-C指針,并將對象所有權轉交給ARC。ARC負責放棄對象的所有權。
例如,如果你有這樣的代碼:

  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命名規則返回Core Foundation類型的方法(參見 Advanced Memory Management Programming Guide)。例如,編譯器知道,在IOS中, UIColorCGColor方法返回的CGColor不會被擁有。你仍需使用合適的類型轉換,如下例所示:

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

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

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

以下方法實現中展示了代碼片段。要注意的是遵從Core Foundation內存管理規則的Core Foundation內存管理函數的用法。

  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. 

 

不要走開,下頁內容更銷魂

#p#

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

  1. [super init]; 

簡單的修正是做如下變換 

  1. self = [super init]; 

更全面的改法是在繼續之前檢測結果是否為nil:

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

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

  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語言結構體重不能使用強類型的ids,例如,以下代碼會編譯不過

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

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

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

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

  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 **.
分配的內存必須是零填充的
你必須在釋放數組(memset或bzero無法工作)之前將每個元素設置為nil.
避免使用memcpy或realloc
ARC運行速度會慢嗎?
這取決于你的測量方式,但基本”很快“。編譯器高效的消除許多外部的 retian和 release調用,而且總的來說會更加關注于提升Objective-C運行時的速度。尤其是,當調用者是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
相關推薦

2024-06-25 08:18:55

2017-07-20 16:55:56

Android事件響應View源碼分析

2020-10-09 08:15:11

JsBridge

2019-07-23 08:55:46

Base64編碼底層

2024-05-17 10:05:06

Java機制應用

2021-04-07 13:28:21

函數程序員異步

2025-01-26 15:38:11

Spring事務編程式

2015-07-15 17:09:48

HiveHadoop分布式文件系統

2022-02-21 09:44:45

Git開源分布式

2019-04-17 15:16:00

Sparkshuffle算法

2021-06-30 00:20:12

Hangfire.NET平臺

2023-05-12 08:19:12

Netty程序框架

2021-04-09 08:40:51

網絡保險網絡安全網絡風險

2017-09-05 08:52:37

Git程序員命令

2025-03-07 08:24:10

Javavolatilecount++

2024-05-10 08:19:59

arthasjava字節碼

2020-10-22 08:25:22

JavaScript運作原理

2019-01-09 10:04:16

2020-02-28 11:29:00

ElasticSear概念類比

2021-07-01 10:01:16

JavaLinkedList集合
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 97免费在线视频 | 免费看日韩视频 | 97人人超碰 | 国产激情在线 | 日本成人午夜影院 | 国精产品一区二区三区 | 精品国产亚洲一区二区三区大结局 | 黄色在线免费观看 | 韩国av一区二区 | 女同久久另类99精品国产 | 成人小视频在线观看 | 欧美在线一区二区视频 | 久久综合狠狠综合久久综合88 | 特级丰满少妇一级aaaa爱毛片 | 欧美一级片在线观看 | 免费a v网站 | 免费观看一级毛片 | 欧美久久久久久 | 国产永久免费 | 日韩黄色小视频 | 九九热在线视频免费观看 | av网站免费在线观看 | 操亚洲| 看毛片的网站 | 最新国产福利在线 | 日韩精品中文字幕在线 | 在线观看www视频 | 欧美日韩三区 | 亚洲成人av| 一级毛片视频在线 | 久久中文字幕一区 | 久草网址 | 亚洲午夜精品久久久久久app | 91社区视频 | 日韩精品一区二区三区视频播放 | 欧美不卡网站 | av毛片| 久草免费在线视频 | 国产精品亚洲一区二区三区在线 | 免费观看一级特黄欧美大片 | 国产精品a久久久久 |