久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

ARC簡(jiǎn)介

 杰出天下 2012-07-06

自動(dòng)內(nèi)存管理技術(shù)(Automatic Reference Counting (ARC))是一個(gè)為Objective-C提供內(nèi)存自動(dòng)管理的編譯期技術(shù)。作為取代使用retain和release方式來管理內(nèi)存的方式,,ARC讓你在其他代碼編寫方面可以放入更多精力,。下圖是兩種管理內(nèi)存方式的對(duì)比。image: Art/ARC_Illustration.jpg

概要說明

ARC的原理是在編譯期為每一個(gè)對(duì)象加入合適的代碼,,以期能否保證這些對(duì)象有合理的生命周期,。從概念上來說,ARC通過增加retain,,release和autorelease等函數(shù),,使得在維護(hù)內(nèi)存計(jì)數(shù)器方面(相關(guān)資料Advanced Memory Management Programming Guide),達(dá)到和手動(dòng)管理內(nèi)存同樣的效果,。

為了達(dá)到產(chǎn)生正確代碼的目的,,ARC禁止一些函數(shù)的調(diào)用和toll-free bridging(相關(guān)資料)的使用。ARC也為內(nèi)存計(jì)數(shù)器和屬性變量引入了新的生命周期,。

ARC在MAC OS X 10.6,10.7(64位應(yīng)用),,iOS4和iOS5中被支持,但是在MAC OS X10.6和iOS4中不支持弱引用(Weak references ),。

Xcode提供一個(gè)能夠自動(dòng)轉(zhuǎn)換工具,,可以把手動(dòng)管理內(nèi)存的代碼來轉(zhuǎn)換成ARC的方式。你也可以為工程中的部分文件指定使用ARC,,而另一部分指定為不使用,。

你可以參考下面的資料:

ARC概述

作為不得不記得何時(shí)調(diào)用retain,releaseautorelease的替代,ARC會(huì)為你的每一個(gè)對(duì)象在編譯期自動(dòng)蘋果,,然后加入合適的函數(shù)調(diào)用來做內(nèi)存管理,,并且編譯器會(huì)自動(dòng)產(chǎn)生合適的dealloc函數(shù)。In general, if you’re only using ARC the traditional Cocoa naming conventions are important only if you need to interoperate with code that uses manual reference counting.(上面這句說什么,?不懂,,不翻譯了)

一個(gè)Person類在使用ARC的情況下可能的實(shí)習(xí)如下:

@interface Person : NSObject
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSNumber *yearOfBirth;
@property (nonatomic, strong) Person *spouse;
@end
 
@implementation Person
@synthesize firstName, lastName, yearOfBirth, spouse;
@end

(關(guān)鍵字strong參考“ARC Introduces New Lifetime Qualifiers”.本文后面就有)

使用ARC,,你可以這樣實(shí)現(xiàn)函數(shù)contrived:

- (void)contrived {
    Person *aPerson = [[Person alloc] init];
    [aPerson setFirstName:@"William"];
    [aPerson setLastName:@"Dudney"];
    [aPerson:setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]];
    NSLog(@"aPerson: %@", aPerson);
}

ARC做內(nèi)存管理,所以Person和NSNumber的對(duì)象都不會(huì)發(fā)生內(nèi)存泄漏,。

你還可以像下面這樣實(shí)現(xiàn)Person類中函數(shù)takeLastNameFrom: :

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

ARC保證oldLastName在NSLog前不會(huì)被是釋放,。

ARC引入的新規(guī)則

ARC能夠起作用引入了一些新的規(guī)則。這些規(guī)則定義了所有的內(nèi)存管理方方面面,,某些規(guī)則是為了更好的體驗(yàn),,還有一些規(guī)則是為了減少編程人員在內(nèi)存管理方面的工作。如果你違反這些規(guī)則,,就會(huì)得到編譯期的錯(cuò)誤,,而不是運(yùn)行期的錯(cuò)誤。

  • 你不能顯示調(diào)用dealloc,不能實(shí)現(xiàn)和顯示調(diào)用retain,release,retainCount和autorelease,。

    當(dāng)然也不能使用@selector(retain)@selector(release)等相關(guān)的功能,。

    你可能為了管理某些不是實(shí)例釋放方面的資源而實(shí)現(xiàn)一個(gè)dealloc。你不用(實(shí)際上是不能)釋放實(shí)例變量,,但是你可能需要為系統(tǒng)類實(shí)例調(diào)用[systemClassInstance setDelegate:nil],,這些是ARC管不到的地方。

    在你實(shí)現(xiàn)的dealloc函數(shù)中不用調(diào)用[super dealloc] (實(shí)際上不行,,因?yàn)闀?huì)得到一個(gè)編譯錯(cuò)誤),。編譯器會(huì)為父類的實(shí)例生成釋放代碼。

    你可以使用CFRetain, CFRelease或其他相關(guān)函數(shù)來管理核心功能的實(shí)例 (相關(guān)內(nèi)容可以查看“Managing Toll-Free Bridging”).

  • 你不能使用NSAllocateObjectNSDeallocateObject.

    你使用alloc來創(chuàng)建實(shí)例,;運(yùn)行期間會(huì)管理這些實(shí)例的釋放,。

  • 你不能在C結(jié)構(gòu)中使用實(shí)例指針。

    與其使用結(jié)構(gòu),,建議你使用Objective-C類來管理數(shù)據(jù),。

  • id和void *不能進(jìn)行隱式轉(zhuǎn)換。

    你必須顯式的告訴編譯器這個(gè)轉(zhuǎn)換的類型,。關(guān)于這個(gè)方面,,可以參考“Managing Toll-Free Bridging”.

  • 不能使用NSAutoreleasePool的實(shí)例.

    作為替代,ARC提供@autoreleasepool塊作為替代,。后者提供了更靈活的方式。

  • 你不能使用內(nèi)存塊,。

    NSZone已經(jīng)被廢氣,,它已經(jīng)給現(xiàn)在的Objective-C運(yùn)行的時(shí)候忽落了。

為了和手動(dòng)管理內(nèi)存相兼容,,ARC定義了函數(shù)和變量命名一條規(guī)則:

  • 屬性變量的命名不能使用new開始,。

ARC引入的新的生存周期修飾符

ARC為實(shí)例引入了幾個(gè)新的生存周期修飾符,特別是自動(dòng)nil化的弱引用,。一個(gè)弱引用并不改變它所指向的實(shí)例的生命周期,,自動(dòng)nil化的弱引用會(huì)在實(shí)例被釋放后自動(dòng)變成nil,。你應(yīng)該妥善使用這些修飾符,ARC對(duì)于強(qiáng)引用(strong)類型提供很多內(nèi)存管理,,因此弱引用用的更多,。

屬性變量

新的關(guān)鍵詞week和strong被引入,如下所示:

// 下面的同義詞是: @property(retain) MyClass *myObject;
@property(strong) MyClass *myObject;
 
//下面的聲明和"@property(assign) MyClass *myObject;"相似
//不過在MyClass的變量被釋放的時(shí)候,,
//這個(gè)屬性變量的值被設(shè)置為nil,,而不是一個(gè)僵尸指針。
@property(weak) MyClass *myObject;

變量修飾符

你可以使用下列關(guān)鍵詞來修飾變量:

__strong
__weak
__unsafe_unretained
__autoreleasing

__strong是缺省的關(guān)鍵詞,。__weak聲明了一個(gè)可以自動(dòng)nil化的弱引用,。__unsafe_unretained聲明一個(gè)弱應(yīng)用,但是不會(huì)自動(dòng)nil化,,也就是說,,如果所指向的內(nèi)存區(qū)域被釋放了,這個(gè)指針就是一個(gè)野指針了,。__autoreleasing用來修飾一個(gè)函數(shù)的參數(shù),,這個(gè)參數(shù)會(huì)在函數(shù)返回的時(shí)候被自動(dòng)釋放。

在對(duì)棧上分配的變量使用__weak修飾符的時(shí)候,,必須加以注意,。考慮下面的情況:

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

雖然這個(gè)NSString的變量初始化后立即賦值給string,,但是由于沒有其他強(qiáng)引用型的指針指向這個(gè)內(nèi)存地址,,所以這個(gè)內(nèi)存地址立即就被釋放了,所以后面的log語句顯示的是一個(gè)空值,。

在傳值方面也需要注意,,下面的代碼是會(huì)有問題的:

NSError *error = nil;
BOOL OK = [myObject performOperationWithError:&error];
if (!OK) {
    // Report the error.
    // ...

但是error變量的聲明類似于:

NSError * __strong e = nil;

函數(shù)的聲明如下:

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

編譯器對(duì)代碼從新處理成下面這個(gè)樣子:

NSError __strong *error = nil;
NSError __autoreleasing *tmp = error;
BOOL OK = [myObject performOperationWithError:&tmp];
error = tmp;
if (!OK) {
    // Report the error.
    // ...

這個(gè)錯(cuò)誤存在于本地變量聲明為__strong,而參數(shù)聲明為__autoreleasing,編譯器在這個(gè)情況下會(huì)生成一個(gè)臨時(shí)變量,。你可以聲明這個(gè)本地變量為id __strong *,或者聲明這個(gè)變量為__autoreleasing,。

譯者注:上面的這段大家再研究一下。我覺得有問題,。

使用生存周期修飾符來避免強(qiáng)引用環(huán)

你可以使用這些生存周期修飾符來避免強(qiáng)引用環(huán),。例如,如果程序中存在父類,,子類,,并且父類需要還有指向子類的指針,那么就有可能存在這樣的引用環(huán),,反之亦然,,那么你可以讓父類中的指針是強(qiáng)類型,子類中指向父類的指針是弱類型。其他的情況需要更精巧的處理,,特別是在塊代碼中的使用,。

在手動(dòng)管理模式下,__block id x; 對(duì)x的內(nèi)存計(jì)數(shù)加一,。在ARC模式下,,__block id x;缺省的對(duì)x的內(nèi)存計(jì)數(shù)加一。為了是這樣的代碼能夠在ARC模式下能夠繼續(xù)工作,,你可以使用__unsafe_unretained __block id x;. 就像__unsafe_unretained名字暗示的那樣,,它也會(huì)有一定的問題 (因?yàn)樗赡鼙环Q為野指針) 。有兩種方式避免上面的問題,,一種是使用__weak (如果不需要支持iOS 4或者OS X v10.6),或者設(shè)置__block的值為nil,。

下面的代碼就是在手動(dòng)模式下的代碼:

MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler =  ^(NSInteger result) {
   [myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
   [myController release];
}];

下面是ARC模式的替代代碼,在__block里面賦值為nil:

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

或者使用__weak修飾詞,,下面的代碼就是一個(gè)演示:

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

在某些情況下,,你可以使用:

MyViewController *myController = [[MyViewController alloc] init…];
// ...
__weak MyViewController *weakMyController = myController;
myController.completionHandler =  ^(NSInteger result) {
    MyViewController *strongMyController = weakMyController;
    if (strongMyController) {
        // ...
        [strongMyController dismissViewControllerAnimated:YES completion:nil];
        // ...
    }
    else {
        // Probably nothing...
    }
};

在某些情況下,比如類不支持__weak模式,,那么你可以使用__unsafe_unretained,。但是你必須保證這個(gè)變量的生命周期,既保證它不能稱為野指針,。

ARC提供了新的語法來替代自動(dòng)釋放池

在ARC模式下,,你不能直接使用NSAutoReleasePool來實(shí)現(xiàn)自動(dòng)釋放池,作為替代,,ARC提供了新的語法:

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

這個(gè)新語句準(zhǔn)許編譯器管理自動(dòng)釋放的狀態(tài),。

在進(jìn)入點(diǎn),自動(dòng)釋放池會(huì)壓入棧中,,當(dāng)正常狀態(tài)退出的時(shí)候,,自動(dòng)釋放池會(huì)被處棧,(break, return, goto, fall-through等情況下),。但是如果在異常的情況下,,自動(dòng)釋放池就不會(huì)有出棧。

這個(gè)語法在所有的Objective-C模式下都能工作,。它比NSAutoReleasePool更有效率,。你需要把所有原先的代碼都改成新的模式。

ARC在Outlet變量方面的規(guī)定

這部分的規(guī)定只有一條,,就是Outlet變量必須使用弱引用,。

關(guān)于這個(gè),請(qǐng)參考Resource Programming Guide中的“Nib Files”節(jié),。

棧上的變量被初始化為nil

使用ARC,,棧上的變量,,不論是強(qiáng)引用,,還是弱引用,,自動(dòng)釋放等類型的,都是會(huì)被隱式的初始化為nil,,比如下面的代碼:

- (void)myMethod {
    NSString *name;
    NSLog(@"name: %@", name);
}

上面的代碼不會(huì)出現(xiàn)運(yùn)行崩潰,,但是會(huì)打印空值。

使用編譯選項(xiàng)來開關(guān)ARC

使用-fobjc-arc打開ARC. 對(duì)于單個(gè)文件,,你可以使用-fno-objc-arc來為某個(gè)你希望使用手動(dòng)管理內(nèi)存的文件來禁用ARC,。

Xcode4.2再M(fèi)AC OS X10.6和10.7(64位應(yīng)用)和iOS 4,iOS5支持ARC,,Mac OS X 10.6和iOS4不支持弱引用,,Xcode4.1以及以前的版本不支持ARC。

管理無損橋接(Toll-Free Bridging)

Toll-Free Bridging,,這個(gè)詞太難翻譯了,,我找了很久也沒有找到一個(gè)合適的翻譯,大家就湊合著看吧

在很多Cocoa程序中,,你會(huì)用到核心基礎(chǔ)框架提供的類的實(shí)例,,不論它是來自核心框架本身 (比如CFArrayRef 或CFMutableDictionaryRef)或者從核心基礎(chǔ)框架延伸出的框架,比如核心圖形框架(比如CGColorSpaceRefCGGradientRef),。

在ARC模式下,,編譯器并不制動(dòng)管理這些核心功能類的實(shí)例,你必須自己調(diào)用CFRetainCFRelease (或者變量的特殊定義的函數(shù))來符合核心基礎(chǔ)的內(nèi)存管理(參考Memory Management Programming Guide for Core Foundation),。

如果你需要基礎(chǔ)核心類實(shí)例和Objective-C類實(shí)例的轉(zhuǎn)換,,你需要使用一個(gè)轉(zhuǎn)換(定義在objc/runtime.h)或者基礎(chǔ)核心類型宏(定義在NSObject.h中)告訴編譯器這個(gè)變量的所屬關(guān)系。

  1. 如果是函數(shù)調(diào)用,,請(qǐng)使用宏,,比如CFBridgingRetain。這些宏使用新的修改算子來做id和void*之間的轉(zhuǎn)換,,并且告訴編譯器關(guān)于這個(gè)void*的內(nèi)存計(jì)數(shù)器的值,。

    NS_INLINE CFTypeRef CFBridgingRetain(id X) {
        return (__bridge_retain CFTypeRef)X;
    }
     
    NS_INLINE id CFBridgingRelease(CFTypeRef X) {
        return (__bridge_transfer id)X;
    }

    仍然需要一個(gè)無操作運(yùn)算符(__bridge)。

  2. 如果你使用C風(fēng)格的轉(zhuǎn)換,,你可以使用直接轉(zhuǎn)換:

    id my_id;
    CFStringRef my_cfref;
    ...
    NSString   *a = (__bridge NSString*)my_cfref;     // Noop cast.
    CFStringRef b = (__bridge CFStringRef)my_id;      // Noop cast.
    ...
    NSString   *c = (__bridge_transfer NSString*)my_cfref; // -1 on the CFRef
    CFStringRef d = (__bridge_retained CFStringRef)my_id;  // returned CFRef is +1

編譯器處理從Cocoa函數(shù)返回的CF實(shí)例

編譯器理解從核心功能函數(shù)返回遵循命名轉(zhuǎn)換的Objective-C實(shí)例的從屬關(guān)系 (參考Advanced Memory Management Programming Guide),。例如,編譯器知道,,在iOS中,,從CGColor函數(shù)返回的CGColor是不從屬于任何實(shí)例的。下面這個(gè)例子是一個(gè)演示:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
        gradientLayer.colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],
                                                         [[UIColor lightGrayColor] CGColor], nil];
        gradientLayer.startPoint = CGPointMake(0.0, 0.0);
        gradientLayer.endPoint = CGPointMake(1.0, 1.0);
    }
    return self;
}

使用在函數(shù)參數(shù)轉(zhuǎn)換的從屬關(guān)鍵詞

當(dāng)在函數(shù)調(diào)用的參數(shù)中使用Objective-C和基礎(chǔ)核心實(shí)例的轉(zhuǎn)換的時(shí)候,,你需要告訴編譯關(guān)于這個(gè)傳入?yún)?shù)的所屬信息,。這些基礎(chǔ)核心實(shí)例的所屬規(guī)則定義在基礎(chǔ)核心內(nèi)存管理規(guī)則中(參考 Memory Management Programming Guide for Core Foundation);Objective-C實(shí)例的規(guī)則定義在Advanced Memory Management Programming Guide.

在下面的代碼片段中,傳入函數(shù)的CGGradientCreateWithColors 的數(shù)組是需要轉(zhuǎn)換的,。byarrayWithObjects:函數(shù)返回的實(shí)例所屬?zèng)]有傳入?yún)?shù),,轉(zhuǎn)換關(guān)鍵詞使用__bridge.

NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],
                                            [[UIColor lightGrayColor] CGColor], nil];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);

下例演示了函數(shù)中的代碼片段的情況,注意所有核心內(nèi)存管理函數(shù)都是遵循基礎(chǔ)核心內(nèi)存管理規(guī)則的,。

- (void)drawRect:(CGRect)rect {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
    CGFloat locations[2] = {0.0, 1.0};
    NSArray *colors = [NSArray arrayWithObjects:[[UIColor darkGrayColor] CGColor],
                                                [[UIColor lightGrayColor] CGColor], nil];
    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.
}

轉(zhuǎn)換舊工程的要點(diǎn)

在擴(kuò)展舊工程的時(shí)候,,你需要注意下面事項(xiàng).

你不能調(diào)用retainrelease,或者 autorelease.

同樣,下面的代碼也不能寫:

while ([x retainCount]) { [x release]; }
你不能調(diào)用dealloc.

一般情況下,,在單例模式下,,或者需要替換實(shí)例的時(shí)候,可能需要在init函數(shù)里面調(diào)用dealloc函數(shù),。對(duì)于單例模式,,你可以使用共享模式來替代。因?yàn)楹笳咴趇nit里面不需要調(diào)用dealloc,在你從新對(duì)self賦值的時(shí)候,,原內(nèi)存就被釋放了,。

你不用使用NSAutoreleasePool對(duì)象

新的@autoreleasepool{}結(jié)構(gòu)是作為一個(gè)替代。它比原先的NSAutoreleasePool快六倍,。@autoreleasepool同樣在手動(dòng)管理內(nèi)存的方式下能夠工作,。

在init方法中,ARC要求把[super init]賦值給self,。

下面的代碼在ARC模式下是不合法的,。

[super init];

簡(jiǎn)單的改成下面這個(gè)樣就可以了:

self = [super init];

一般還需要檢查返回值:

self = [super init];
if (self) {
   ...
你不能實(shí)現(xiàn)自己的retain和release方法。

實(shí)現(xiàn)自己的retain或release方法會(huì)破壞弱指針,,這里有一些理由阻止你這樣做:

  • 性能.

    請(qǐng)不要實(shí)現(xiàn)這些函數(shù),,因?yàn)樵贜SObject中的實(shí)現(xiàn)快多了,如果你發(fā)現(xiàn)問題,,那么需要改掉這些問題,,而不是再次實(shí)現(xiàn)這些函數(shù)。

  • 為了實(shí)現(xiàn)弱指針To implement a custom weak pointer system.

    使用__weak來替代這些函數(shù)的實(shí)現(xiàn).

  • 為了實(shí)現(xiàn)單例模式,。

    使用共享模式,。或者,,使用類級(jí)別函數(shù),,這樣根本不需要申請(qǐng)實(shí)例。

如果你發(fā)現(xiàn)不得不實(shí)現(xiàn)retain或者release函數(shù),,那么請(qǐng)?jiān)陬愔袑?shí)現(xiàn)下面的函數(shù):

-(BOOL)supportsWeakPointers { return NO; }

上面的函數(shù)阻止為你的類生成弱指針,。不過還是強(qiáng)烈建議你使用其他的方式來避免實(shí)現(xiàn)這些函數(shù)。

不能在C語言的結(jié)構(gòu)中使用strong ids,。

比如,,下面的代碼不能被編譯:

struct X { id x; float y; };

因?yàn)閤并定義強(qiáng)引用,,那么編譯器就不能為它生成按照的管理代碼。例如,,如果x以及被賦值,,那么在這個(gè)結(jié)構(gòu)的指針被free前,必須先釋放這些x指向的內(nèi)存,,但是由于是ARC模式,所以這些內(nèi)存就被泄漏了,,所以在C語言的結(jié)構(gòu)中,,ARC禁止使用強(qiáng)指針,下面是可能的解決方案:

  1. 使用類來代替結(jié)構(gòu),。

    這是最好的方式,。

  2. 如果在使用類有性能問題(比如你需要一個(gè)很大的結(jié)構(gòu)的數(shù)組),那么可以使用void*來代替,。

    這需要顯式的轉(zhuǎn)換,,下面會(huì)有討論。

  3. 把這個(gè)變量用__unsafe_unretained修飾,。

    這個(gè)會(huì)對(duì)下面的情況會(huì)有幫助:

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

    你可以這樣定義結(jié)構(gòu):

    struct x { __unsafe_unretained NSString *S; int X; }

    這樣的寫法可能會(huì)有很大的問題,,如果在指針里面的實(shí)例被釋放了。but it is very useful for things that are known to be around forever like constant string literals.

你不能直接進(jìn)行id和void *的轉(zhuǎn)換(包括核心功能中的類型),。

這個(gè)問題的細(xì)節(jié)在 “Managing Toll-Free Bridging”里面討論,。

常見問題解答

ARC的機(jī)制是什么?它在那里放入retain/release函數(shù)調(diào)用,?

請(qǐng)停止思考這些問題,,把更多的精力放在下面的問題上,比如你的程序邏輯,,對(duì)象的強(qiáng),,弱引用,對(duì)象的所屬關(guān)系,,可能的循環(huán)引用等問題上,。

我還需要為我的類寫一個(gè)dealloc函數(shù)么?

可能,。

因?yàn)锳RC并不自動(dòng)調(diào)用malloc/free,并不自動(dòng)管理像核心功能對(duì)象,、文件描述符等的生命周期,所以你仍然需要在dealloc中釋放它們,。

你不會(huì)(實(shí)際上是不能)釋放對(duì)象實(shí)例,,但是你仍然需要為系統(tǒng)類調(diào)用[self setDelegate:nil]或其他ARC不會(huì)自動(dòng)生產(chǎn)釋放代碼的情況下釋放資源。

dealloc方法在ARC不是必須的,,并且不許調(diào)用[super dealloc],。

ARC中會(huì)出現(xiàn)循環(huán)引用(retain cycles)么,?

是的。

ARC自動(dòng)產(chǎn)生retain/release函數(shù),,同時(shí)也繼承了產(chǎn)生循環(huán)引用的機(jī)制,。幸運(yùn)的是,ARC很少有內(nèi)存泄漏,,因?yàn)樵诼暶鲗傩缘淖兞康臅r(shí)候決定是否使用retain,。

注:請(qǐng)搜索什么是retain cycles.

ARC下面的塊代碼如何工作?

塊代碼在ARC方式下,只能在棧上傳遞的方式下工作,,比如在return語句中,。你不用在調(diào)用Block Copy。你還是必須在為arrayWithObjects: 傳入棧的時(shí)候使用[^{} copy]和其他的retain功能的函數(shù),。

有一件事情需要提到,,在ARC方式下,__block NSString *S是可以使用,,它不是一個(gè)野指針,。使用_block __unsafe_unretained NSString *S 或者 (更好的方式) __block __weak NSString *S.

我能在雪豹(Snow Leopard)上的XCode為MAC OS X開發(fā)應(yīng)用的時(shí)候使用ARC么?

不能,,那個(gè)版本的Xcode4.2不支持ARC,。雪豹版本沒有10.7的SDK,所以在為MAC OS X開發(fā)應(yīng)用的時(shí)候不能使用ARC,,但是這個(gè)版本支持為iOS開發(fā)的時(shí)候使用ARC,。獅子(Lion)版本的是可以的。

在支持ARC的工程中我能創(chuàng)建實(shí)例數(shù)組么,?

是的,,你可以,如下例所示:

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

這里有幾點(diǎn)需要注意的地方:

  • 你必須在某些情況下寫__strong SomeClass **,,因?yàn)槿绻悴粚?,缺省的?/code>__autoreleasing SomeClass **.

  • 申請(qǐng)的內(nèi)存必須使用0填充。

  • 在釋放這個(gè)數(shù)組前,,你必須設(shè)置每一個(gè)元素為nil(調(diào)用memset,,并傳入0是沒有用的)。

  • 你必須避免使用memcpy或realloc,。

ARC慢么,?

這個(gè)取決你如何衡量這個(gè)問題了,不過一般來說,,這個(gè)問題的答案是“no”,。下面是原文的解釋,我總結(jié)的是要相信編譯器在這個(gè)方面的能力,。It depends on what you’re measuring, but generally “no.” The compiler efficiently eliminates many extraneousretain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common “return a retain/autoreleased object” pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.

One issue to be aware of is that the optimizer is not run in common debug configurations, so expect to see a lot more retain/release traffic at-O0 than at-Os.

在ObjC++模式,,ARC能否工作?

式的,,你甚至可以在類或者容器中使用strong/weak id。為了能正常工作,,ARC在編譯期間會(huì)在復(fù)制構(gòu)造函數(shù)和析構(gòu)函數(shù)中加入retain/release方面的邏輯,。一個(gè)事情需要避免的就是,你不能為某些指針使用__strong,,例如:

std::vector<__strong NSString*> V;

那些類不支持自動(dòng)nil化的弱引用,?

下面的類的實(shí)例不能使用自動(dòng)nil化的弱引用

NSATSTypesetterNSColorSpaceNSFontNSFontManagerNSFontPanelNSImage,NSMenuView,NSParagraphStyle,NSSimpleHorizontalTypesetter,NSTableCellView,NSTextView,NSViewController,NSWindow, andNSWindowController. 還有,OS X上的AV Foundation框架中所有類都不支持自動(dòng)nil化的弱引用,。

如果屬性變量是這些類的實(shí)例的時(shí)候,,使用assign來替代weak;作為變量,,使用__unsafe_unretained來替代__weak。

此外,,你也不用對(duì)NSHashTable,NSMapTable, 和NSPointerArray的實(shí)例做弱應(yīng)用,。


在寫類似于NSCell這樣使用了NSCopyOjbect的子類的時(shí)候有什么需要特別關(guān)注的地方么?

沒有什么特別的,,ARC會(huì)做一切事情,。

我可以為每一個(gè)文件單獨(dú)指定是否使用ARC么?

是的,。

當(dāng)你為一個(gè)舊的工程添加ARC是,,編譯選項(xiàng)-fobjc-arc對(duì)所有的文件都是有效的。你可以使用編譯選項(xiàng)-fno-objc-arc為某個(gè)類單獨(dú)禁止ARC,。在target上的Build Phases 頁,打開Compile Sources組,,這里有一個(gè)文件列表,雙擊某個(gè)文件,,加入-fno-objc-arc就可以為這個(gè)文件禁用ARC,。

image: Art/fno-objc-arc.png

GC (Garbage Collection)是否被廢棄了?

GC在10.7系統(tǒng)中被支持,但是強(qiáng)烈建議在新工程中使用ARC,,對(duì)于你老的代碼,,你可以做一下轉(zhuǎn)換,比較工作量不大,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多