OC中的__autoreleasing

OC采用了ARC之后編譯器給我們的代碼插入內(nèi)存管理代碼。

__strong

聲明一個(gè)對(duì)象,默認(rèn)是以__strong修飾的,當(dāng)沒有任何地方引用這個(gè)對(duì)象時(shí),對(duì)象會(huì)釋放。

// ARC下的普通變量的傳值
obj1 = obj2;

// ARC下編譯器會(huì)改寫為
// 新引用了obj2
// [obj2 reatain];
// 由于不再引用obj1
// [obj1 release];
// 完成賦值操作
// obj1 = obj2;

__autoreleasing

那么對(duì)于今天要說的__autoreleasing類型的變量呢, 被__autoreleasing修飾的變量特點(diǎn)是在當(dāng)前autoreleasepool作用域內(nèi)有效,出了當(dāng)前的autoreleasepool會(huì)被自動(dòng)釋放,不同于默認(rèn)的__strong變量,沒有引用時(shí)才會(huì)釋放。

// autoreleasing變量和普通變量傳值
NSObject * __autoreleasing auto1 = nil;
auto1 = obj1;

// ARC下編譯器會(huì)改寫
// 因?yàn)閍uto1需要保證引用對(duì)象在當(dāng)前autoreleasepool作用域內(nèi)有效
// [obj1 retain];
// [obj1 autorelease];
// auto1 = obj1;
    
// autoreleasing變量和autoreleasing變量傳值
auto1 = auto2;
// ARC下編譯器不需要改寫,因?yàn)閍uto2已經(jīng)是在當(dāng)前autoreleasepool作用域內(nèi)有效
// auto1 = obj1;

我們注意到__autoreleasing對(duì)象之間傳值不需要做任何處理,這是一個(gè)很好的特性,二級(jí)指針傳遞對(duì)象時(shí),接收和被傳遞的對(duì)象都需要被修飾成__autoreleasing,這樣的話ARC下編譯器不需要對(duì)傳遞過程做任何干預(yù),實(shí)際上要在二級(jí)指針傳值過程中自動(dòng)插入代碼并不太容易。

- (void)autoreleasingTestCase {
    
    // 獲取方法返回的error
    NSError * __autoreleasing error = nil;
    [self autoreleasingTestForError:&error];
    
    //@note:
    // 如果我們寫的不標(biāo)準(zhǔn)
    // NSError * error = nil;
    // [self autoreleasingTestForError:&error];
    // 實(shí)際代碼被改寫成這樣,
    // 所以我們會(huì)發(fā)現(xiàn):autoreleasingTestForError打印errotPtr地址和&error不一致
    // NSError * error = nil;
    // NSError * __autoreleasing tmp = error;
    // [self autoreleasingTestForError:&tmp];
    // error = tmp;
}

// (NSError * __autoreleasing *)error表示error是指向一個(gè)__autoreleasing修飾的error對(duì)象
// @note:
// 如果我們寫成這樣(NSError **)error,實(shí)際上編譯器會(huì)認(rèn)為是(NSError * __autoreleasing *)error
// 這點(diǎn)可以通過自動(dòng)補(bǔ)全的提示發(fā)現(xiàn),提示是帶有__autoreleasing的
// 雖然使用上沒有問題,但是依然建議按照規(guī)范來聲明
- (void)autoreleasingTestForError:(NSError * __autoreleasing *)errorPtr {
    NSError * __autoreleasing errorObj = [[NSError alloc]init];
    // 給外部傳入的error變量賦值
    *errorPtr = errorObj;
    
    // @note:
    // 如果errorObj不是__autoreleasing修飾的,那么編譯器會(huì)做一些修改
    // NSError * errorObj = [[NSError alloc]init];
    // NSError * __autoreleasing tmp = errorObj;
    // *errorPtr = tmp;
}

盡管編譯器做了容錯(cuò)處理,在明白了__autoreleasing的特性之后,依然建議按照規(guī)范的格式編寫代碼,編譯器的容錯(cuò)并不一定可靠或者會(huì)帶來不必要的開銷。

更多技術(shù)參考:https://developer.apple.com/library/archive/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容