OC中引用計(jì)數(shù)的理解

基于OC中內(nèi)存管理的一些理解
下面是本人的一些理解

  • 自己生成的對象雏亚,自己所持有
  • 非自己生成的對象,自己也能持有
  • 不再需要自己持有的對象時(shí)釋放
  • 非自己持有的對象無法釋放
對象操作 OC方法
生成并持有對象 alloc/new/copy/mutableCopy
持有對象 retain方法
釋放對象 release方法
廢棄對象 dealloc方法
這里解釋一下release方法和dealloc方法的區(qū)別

release方法主要是在MRC下釋放Foundation框架下面創(chuàng)建的對象狐史,在ARC下面是系統(tǒng)自動(dòng)的釋放
dealloc方法是釋放UIKit框架創(chuàng)建的UI界面的內(nèi)存
(小弟的理解就是這樣的,如果有錯(cuò)請大佬指點(diǎn)出來)

自己生成的對象说墨,自己所持有

使用以下名稱開頭的方法名意味著自己生成的對象只有自己持有

  • alloc
  • new
  • copy
  • mutableCopy
/*
*自己生成并持有的對象
*/
id obj = [[NSobject alloc]init];
/*
*這樣創(chuàng)建的對象引用計(jì)數(shù)+1
*/

非自己生成的對象骏全,自己也能持有

用上述方法以外取得的對象,即alloc/new/copy/mutableCopy以外的方法獲取的對象尼斧,因?yàn)榉亲约荷刹⒊钟薪保宰约翰皇窃搶ο蟮某钟姓撸热鏝SMutableArray類的array類方法創(chuàng)建的對象

/*
*取得非自己生成并持有的對象
*/
id obj = [NSMutableArray array];
/*
*源碼中棺棵,NSMutableArray類對象被賦給變量obj楼咳,但變量obj自己并沒有持有該對象。
*/
[obj retain];//obj對象的引用計(jì)數(shù)+1烛恤,調(diào)用retain方法之后就變?yōu)樽约核钟?

不再需要自己持有的對象時(shí)釋放

/*
*自己創(chuàng)建并持有的方法
*/
 id obj = [NSObject new];
/*
*當(dāng)自己不需要的時(shí)候立即釋放
*/
[obj release]母怜;

非自己持有的對象無法釋放

對于自身創(chuàng)建的對象或者持有的對象,在不使用的時(shí)候必須釋放掉
倘若在程序中釋放了非自己所持有的對象程序就會(huì)崩潰

id obj = [NSObject new];
[obj release];
/*
*當(dāng)自身釋放了再次釋放之后系統(tǒng)就會(huì)崩潰
*/
[obj release];

ARC規(guī)則

在便以單位上缚柏,可設(shè)置ARC有效或者無效
一個(gè)應(yīng)用程序可以混合ARC有效或無效的二進(jìn)制形勢
設(shè)置ARC有效的編譯方式如下所示

  • 使用clang(LLVM編譯器)3.0或以上版本
  • 指定編譯器屬性為“-fobjc-arc”
    當(dāng)然在Xcode4.2及以上的版本默認(rèn)設(shè)置的對所有的文件ARC有效
    當(dāng)然MRC的內(nèi)存管理方式對于ARC一樣的適用苹熏,即:
  • 自己生成的對象,自己所持有
  • 非自己生成的對象,自己也能持有
  • 不再需要自己持有的對象時(shí)釋放
  • 非自己持有的對象無法釋放

權(quán)限修飾符

  • __strong
  • __weak
  • __unsafc_unretained
  • __autoreleasing

__strong

__strong修飾符是id類型和對象類型默認(rèn)的所有權(quán)限修飾符轨域。也就是說袱耽,以下源代碼中的id變量,實(shí)際上被附加了所有權(quán)限修飾符
id obj = [[NSObject alloc]init];
id和對象類型在沒有明確指定所有權(quán)限修飾符時(shí)干发,默認(rèn)__strong修飾符朱巨,上面的源代碼與以下相同
id __strong obj = [[NSObject alloc]init];
該源代碼在ARC無效時(shí)的表述

/*ARC無效*/
id obj = [[NSObject alloc]init];
{
   /*
    *自己生成并且自己所持有
   */
    id __strong obj = [[NSObject alloc]init];
}
//此源碼明確的指定了c語言的變量的作用域,ARC無效時(shí)铐然,該源代碼可描述如下:
/*ARC無效*/
{
   id obj = [[NSObject alloc]init];
   [obj release];
}
/*
*因?yàn)樽兞磕J(rèn)為__strong修飾,當(dāng)obj超出了其作用域恶座,強(qiáng)引用就會(huì)失效
*并且對象所有者不存在搀暑,因此廢棄該對象
*/

以上是__strong修飾符修飾的自己創(chuàng)建并且自己持有的對象的源碼分析
下面簡單的說一下非自己生成并持有對象的源碼

{
  id __strong obj = [NSMutableArray array];
}
//在NSMutableArray類的array類方法的源碼中取得非自己生成并持有的對象
{
/*取得非自己生成并持有*/
 id __strong obj = [NSMutableArray array];
/*
*因?yàn)樽兞縪bj是強(qiáng)引用,所以自己持有
*/
}
/*
*變量obj超出了作用域跨琳,強(qiáng)引用失效自点,自己釋放自己持有的對象
*/

其實(shí)附有__strong修飾符的變量之間可以相互賦值

id __strong obj0 = [[NSObject alloc]init];
id __strong obj1 = [[NSObject alloc]init];
id __strong obj2 = nill;
obj0 = obj1;
obj2 = obj0;
obj0 = nil;
obj1 = nil;
obj2 = nil;

當(dāng)然,即便是OC類成員變量脉让,也可以在方法參數(shù)上桂敛,使用附有__strong修飾符的變量

@interface Test : NSObject
{
    id __strong obj_;
}
- (void)setObject:(id __strong)obj;
@end
@implementation Test
- (instancetype)init{
    self = [super init];
    if (self) {
        
    }
    return self;
}
- (void)setObject:(id __strong)obj{
    obj_ = obj;
}
@end

正如蘋果粑粑說的那樣,通過__strong修飾符溅潜,不必再次鍵入retain和release术唬,滿足了“引用計(jì)數(shù)式管理的思考方式”

__weak

看起來好像通過__strong修飾符編譯器就能完美的進(jìn)行內(nèi)存管理,但是遺憾的是滚澜,僅通過__strong修飾符是不能解決有些重大的問題
這里所有的重大的問題就是引用計(jì)數(shù)式內(nèi)存管理中必然會(huì)發(fā)生的“循環(huán)引用”的問題


D4922A20-A7D5-4DDF-8DA5-44823F395BC3.png

例如:前面我們的帶有__strong 的例子就容易發(fā)生循環(huán)引用

@interface Test : NSObject
{
    id __strong obj_;
}
- (void)setObject:(id __strong)obj;
@end
@implementation Test
- (instancetype)init{
    self = [super init];
    if (self) {
        
    }
    return self;
}
- (void)setObject:(id __strong)obj{
    obj_ = obj;
}
@end
//以下為循環(huán)引用
{
 id test0 = [Test new];//對象A
 id test1 = [Test new];//對象B
 [test0 setObject: test1];//對象A的obj_成員變量持有對象B的強(qiáng)引用
 [test1 setObject:test0];//對象B的obj_成員變量持有對象A的強(qiáng)引用
}

循環(huán)引用很容易造成內(nèi)存泄漏


0C22C36C-812B-4821-8A00-973B886A7D3C.png

上面這種情況是兩個(gè)相互強(qiáng)引用發(fā)生的內(nèi)存泄漏粗仓,下面這種是自身強(qiáng)引用自身發(fā)生的內(nèi)存泄漏

id test = [Test new];
[test setObject: test];

既然出現(xiàn)了這種強(qiáng)引用的內(nèi)存泄漏,那么蘋果粑粑就會(huì)解決這種內(nèi)存泄漏设捐,和__strong對應(yīng)的修飾符__weak借浊,如:
id __weak obj = [NSObject new];
變量obj上附加__weak修飾符,但是這樣編譯之后萝招,編譯器會(huì)發(fā)出警告
Assigning retained object to weak variable; object will be released after assignment
很顯然蚂斤,編譯器的意思就是很容易造成提前釋放,有問題就要解決
id __strong obj0 = [NSObject new];
id __weak obj1 = obj0槐沼;
這樣賦值就不會(huì)出現(xiàn)警告
當(dāng)然__weak還有一個(gè)優(yōu)點(diǎn)曙蒸,在持有某個(gè)對象的弱引用時(shí),若該對象被廢棄岗钩,則此弱引用將自動(dòng)失效且處于nil被賦值的狀態(tài),代碼如下:

        id __weak obj1 = nil;
        {
            id __strong obj0 = [NSObject new];
            obj1 = obj0;
            NSLog(@"A:obj1:%@",obj1);
        }
        NSLog(@"B:obj1:%@",obj1);

此源碼執(zhí)行的結(jié)果:
A:obj1:<NSObject: 0x103000db0>
B:obj1:(null)
但是有個(gè)注意事項(xiàng):__weak修飾符只能用于iOS5以上及OS X Lion以上版本的應(yīng)用逸爵,在iOS4以下及OS X Snow Leopard 的應(yīng)用程序中可使用__unsafe _unretained 來修飾,但是對于現(xiàn)在來說也沒有多少人在使用iOS4以下及OS X Snow Leopard版本了

__unsafe _unretained

__unsafe _unretained 和__weak是相同的凹嘲,這里就不過多的講解师倔,但是要注意的是__unsafe _unretained是不安全的權(quán)限修飾符

__autoreleasing

ARC有效時(shí)不能使用autorelease和NSAutoreleasePool類,雖然autorelease無法直接使用,但是在ARC有效時(shí)autorelease功能是起作用的

/*ARC無效*/
NSAutoreleasePool *pool = [NSAutoreleasePool new];
id obj = [NSObject new];
[obj autorelease];
[pool drain];
  /*ARC有效*/    
@autoreleasepool {
          id __autoreleasing obj = [NSObject new];
}

指定“@autoreleasepool代碼塊”來替代“ NSAutoreleasePool”
另外趋艘,在ARC有效時(shí)疲恢,要通過將對象賦值給附加了__autoreleasing修飾符的變量來替代調(diào)用autorelease方法,對象賦值給附有__autoreleasing修飾符的變量等價(jià)于ARC無效時(shí)調(diào)用對象的autorelease方法瓷胧,即對象被注冊到autoreleasepool
換一種說話就是在ARC有效時(shí)显拳,用@autoreleasepool塊替代NSAutoreleasePool類,用附有__autoreleasing修飾符的變量替代autorelease方法搓萧,圖解:


86FB4C33-7785-4D36-BFFB-605C4042E57B.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末杂数,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瘸洛,更是在濱河造成了極大的恐慌揍移,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件反肋,死亡現(xiàn)場離奇詭異那伐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)石蔗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門罕邀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人诉探,你說我怎么就攤上這事」餮幔” “怎么了阵具?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長定铜。 經(jīng)常有香客問我阳液,道長,這世上最難降的妖魔是什么揣炕? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任帘皿,我火速辦了婚禮,結(jié)果婚禮上畸陡,老公的妹妹穿的比我還像新娘鹰溜。我一直安慰自己,他們只是感情好丁恭,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布曹动。 她就那樣靜靜地躺著,像睡著了一般牲览。 火紅的嫁衣襯著肌膚如雪墓陈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音贡必,去河邊找鬼兔港。 笑死,一個(gè)胖子當(dāng)著我的面吹牛仔拟,可吹牛的內(nèi)容都是我干的衫樊。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼利花,長吁一口氣:“原來是場噩夢啊……” “哼科侈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起炒事,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤臀栈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后羡洛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體挂脑,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡藕漱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年欲侮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肋联。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡威蕉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出橄仍,到底是詐尸還是另有隱情韧涨,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布侮繁,位于F島的核電站虑粥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宪哩。R本人自食惡果不足惜娩贷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锁孟。 院中可真熱鬧彬祖,春花似錦、人聲如沸品抽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽圆恤。三九已至突倍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赘方。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工烧颖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人窄陡。 一個(gè)月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓炕淮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親跳夭。 傳聞我的和親對象是個(gè)殘疾皇子涂圆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容