ios面試之內(nèi)存管理

最近老問(wèn)這個(gè)堕伪,但是每個(gè)人的理解不一樣,其實(shí)我也不知道應(yīng)該咋說(shuō)

*基本概念
引用計(jì)數(shù)(Reference Count)

*內(nèi)存釋放的原則
手動(dòng)管理內(nèi)存有時(shí)候并不容易它浅,因?yàn)閷?duì)象的引用有時(shí)候是錯(cuò)綜復(fù)雜的玖翅,對(duì)象之間可能互相交叉引用唐全,此時(shí)需要遵循一個(gè)法則:誰(shuí)創(chuàng)建,誰(shuí)釋放接癌。

*屬性參數(shù)

*自動(dòng)釋放池
在ObjC中也有一種內(nèi)存自動(dòng)釋放的機(jī)制叫做“自動(dòng)引用計(jì)數(shù)”(或“自動(dòng)釋放池”)心赶,與C#、Java不同的是缺猛,這只是一種半自動(dòng)的機(jī)制缨叫,有些操作還是需要我們手動(dòng)設(shè)置的。自動(dòng)內(nèi)存釋放使用@autoreleasepool關(guān)鍵字聲明一個(gè)代碼塊荔燎,如果一個(gè)對(duì)象在初始化時(shí)調(diào)用了autorelase方法耻姥,那么當(dāng)代碼塊執(zhí)行完之后,在塊中調(diào)用過(guò)autorelease方法的對(duì)象都會(huì)自動(dòng)調(diào)用一次release方法有咨。這樣一來(lái)就起到了自動(dòng)釋放的作用琐簇,同時(shí)對(duì)象的銷毀過(guò)程也得到了延遲(統(tǒng)一調(diào)用release方法)

在開(kāi)發(fā)中,我們常常都會(huì)使用到局部變量座享,局部變量一個(gè)特點(diǎn)就是當(dāng)它超過(guò)作用域時(shí)婉商,就會(huì)自動(dòng)釋放。而autorelease pool跟局部變量類似渣叛,當(dāng)執(zhí)行代碼超過(guò)autorelease pool塊時(shí)丈秩,所有放在autorelease pool的對(duì)象都會(huì)自動(dòng)調(diào)用release。它的工作原理如下:

創(chuàng)建一個(gè)NSAutoreleasePool對(duì)象
在autorelease pool塊的對(duì)象調(diào)用autorelease方法
釋放NSAutoreleasePool對(duì)象

對(duì)于自動(dòng)內(nèi)存釋放簡(jiǎn)單總結(jié)一下:
autorelease方法不會(huì)改變對(duì)象的引用計(jì)數(shù)器淳衙,只是將這個(gè)對(duì)象放到自動(dòng)釋放池中蘑秽;
自動(dòng)釋放池實(shí)質(zhì)是當(dāng)自動(dòng)釋放池銷毀后調(diào)用對(duì)象的release方法挽唉,不一定就能銷毀對(duì)象(例如如果一個(gè)對(duì)象的引用計(jì)數(shù)器>1則此時(shí)就無(wú)法銷毀);
由于自動(dòng)釋放池最后統(tǒng)一銷毀對(duì)象筷狼,因此如果一個(gè)操作比較占用內(nèi)存(對(duì)象比較多或者對(duì)象占用資源比較多)瓶籽,最好不要放到自動(dòng)釋放池或者考慮放到多個(gè)自動(dòng)釋放池;
ObjC中類庫(kù)中的靜態(tài)方法一般都不需要手動(dòng)釋放埂材,內(nèi)部已經(jīng)調(diào)用了autorelease方法

ARC管理方法

iOS/OS X內(nèi)存管理方法有兩種:手動(dòng)引用計(jì)數(shù)(Manual Reference Counting)和自動(dòng)引用計(jì)數(shù)(Automatic Reference Counting)塑顺。從OS X Lion和iOS 5開(kāi)始,不再需要程序員手動(dòng)調(diào)用retain和release方法來(lái)管理Objective-C對(duì)象的內(nèi)存俏险,而是引入一種新的內(nèi)存管理機(jī)制Automatic Reference Counting(ARC)严拒,簡(jiǎn)單來(lái)說(shuō),它讓編譯器來(lái)代替程序員來(lái)自動(dòng)加入retain和release方法來(lái)持有和放棄對(duì)象的所有權(quán)竖独。

在ARC內(nèi)存管理機(jī)制中裤唠,id和其他對(duì)象類型變量必須是以下四個(gè)ownership qualifiers其中一個(gè)來(lái)修飾:

__strong(默認(rèn),如果不指定其他莹痢,編譯器就默認(rèn)加入)
__weak
__unsafe_unretained
__autoreleasing
所以在管理Objective-C對(duì)象內(nèi)存的時(shí)候种蘸,你必須選擇其中一個(gè),下面會(huì)用一些列子來(lái)逐個(gè)解釋它們的含義以及如何選擇它們竞膳。

__strong ownership qualifier
如果我想創(chuàng)建一個(gè)字符串航瞭,使用完之后將它釋放調(diào)用

{
    NSString *text = [[NSString alloc] initWithFormat:@"Hello, world"];   //@"Hello, world"對(duì)象的RC=1
    NSLog(@"%@", text);
    [text release];                      //@"Hello, world"對(duì)象的RC=0
}

而如果是使用ARC方式的話,就text對(duì)象無(wú)需調(diào)用release方法坦辟,而是當(dāng)text變量超過(guò)作用域時(shí)刊侯,編譯器來(lái)自動(dòng)加入[text release]方法來(lái)釋放內(nèi)存

{
    NSString *text = [[NSString alloc] initWithFormat:@"Hello, world"];    //@"Hello, world"對(duì)象的RC=1
    NSLog(@"%@", text);
}
/*
 *  當(dāng)text超過(guò)作用域時(shí),@"Hello, world"對(duì)象會(huì)自動(dòng)釋放锉走,RC=0
 */

而當(dāng)你將text賦值給其他變量anotherText時(shí)滨彻,MRC需要retain一下來(lái)持有所有權(quán),當(dāng)text和anotherText使用完之后挪蹭,各個(gè)調(diào)用release方法來(lái)釋放亭饵。

{
    NSString *text = [[NSString alloc] initWithFormat:@"Hello, world"];    //@"Hello, world"對(duì)象的RC=1
    NSLog(@"%@", text);
    NSString *anotherText = text;        //@"Hello, world"對(duì)象的RC=1
    [anotherText retain];                //@"Hello, world"對(duì)象的RC=2
    NSLog(@"%@", anotherText);
    [text release];                      //@"Hello, world"對(duì)象的RC=1
    [anotherText release];               //@"Hello, world"對(duì)象的RC=0
}

而使用ARC的話,并不需要調(diào)用retain和release方法來(lái)持有跟釋放對(duì)象嚣潜。

{
    NSString *text = [[NSString alloc] initWithFormat:@"Hello, world"];   //@"Hello, world"對(duì)象的RC=1
    NSLog(@"%@", text);
    NSString *anotherText = text;        //@"Hello, world"對(duì)象的RC=2
    NSLog(@"%@", anotherText);
}
/*
 *  當(dāng)text和anotherText超過(guò)作用域時(shí)冬骚,會(huì)自動(dòng)調(diào)用[text release]和[anotherText release]方法, @"Hello, world"對(duì)象的RC=0
 */

除了當(dāng)__strong變量超過(guò)作用域時(shí)懂算,編譯器會(huì)自動(dòng)加入release語(yǔ)句來(lái)釋放內(nèi)存只冻,如果你將__strong變量重新賦給它其他值,那么編譯器也會(huì)自動(dòng)加入release語(yǔ)句來(lái)釋放變量指向之前的對(duì)象计技。例如:

{
    NSString *text = [[NSString alloc] initWithFormat:@"Hello, world"];    //@"Hello, world"對(duì)象的RC=1
    NSString *anotherText = text;        //@"Hello, world"對(duì)象的RC=2
    NSString *anotherText = [[NSString alloc] initWithFormat:@"Sam Lau"];  // 由于anotherText對(duì)象引用另一個(gè)對(duì)象@"Sam Lau"喜德,那么就會(huì)自動(dòng)調(diào)用[anotherText release]方法,使得@"Hello, world"對(duì)象的RC=1, @"Sam Lau"對(duì)象的RC=1
}
/*
 *  當(dāng)text和anotherText超過(guò)作用域時(shí)垮媒,會(huì)自動(dòng)調(diào)用[text release]和[anotherText release]方法舍悯,
 *  @"Hello, world"對(duì)象的RC=0和@"Sam Lau"對(duì)象的RC=0
 */

如果變量var被__strong修飾航棱,當(dāng)變量var指向某個(gè)對(duì)象objc,那么變量var持有某個(gè)對(duì)象objc的所有權(quán)

前面已經(jīng)提過(guò)內(nèi)存管理的四條規(guī)則:


1455699806540113.png

我們總結(jié)一下編譯器是按以下方法來(lái)實(shí)現(xiàn)的:
對(duì)于規(guī)則1和規(guī)則2萌衬,是通過(guò)__strong變量來(lái)實(shí)現(xiàn)饮醇,

對(duì)于規(guī)則3來(lái)說(shuō),當(dāng)變量超過(guò)它的作用域或被賦值或成員變量被丟棄時(shí)就能實(shí)現(xiàn)

對(duì)于規(guī)則4秕豫,當(dāng)RC=0時(shí)朴艰,系統(tǒng)就會(huì)自動(dòng)調(diào)用

__weak ownership qualifier
其實(shí)編譯器根據(jù)__strong修飾符來(lái)管理對(duì)象內(nèi)存。但是__strong并不能解決引用循環(huán)(Reference Cycle)問(wèn)題:對(duì)象A持有對(duì)象B混移,反過(guò)來(lái)祠墅,對(duì)象B持有對(duì)象A;這樣會(huì)導(dǎo)致不能釋放內(nèi)存造成內(nèi)存泄露問(wèn)題歌径。

1455699911695766.png

引用Pro Multithreading and Memory Management for iOS and OS X的圖

舉一個(gè)簡(jiǎn)單的例子毁嗦,有一個(gè)類Test有個(gè)屬性objc,有兩個(gè)對(duì)象test1和test2的屬性objc互相引用test1和test2:

@interface Test : NSObject

@property (strong, nonatomic) id objc;

@end
{
    Test *test1 = [Test new];        /* 對(duì)象a */
    /* test1有一個(gè)強(qiáng)引用到對(duì)象a */
    Test *test2 = [Test new];        /* 對(duì)象b */
    /* test2有一個(gè)強(qiáng)引用到對(duì)象b */
    test1.objc = test2;              /* 對(duì)象a的成員變量objc有一個(gè)強(qiáng)引用到對(duì)象b */
    test2.objc = test1;              /* 對(duì)象b的成員變量objc有一個(gè)強(qiáng)引用到對(duì)象a */
}
/*   當(dāng)變量test1超過(guò)它作用域時(shí)回铛,它指向a對(duì)象會(huì)自動(dòng)release
 *   當(dāng)變量test2超過(guò)它作用域時(shí)狗准,它指向b對(duì)象會(huì)自動(dòng)release
 *   此時(shí),b對(duì)象的objc成員變量仍持有一個(gè)強(qiáng)引用到對(duì)象a
 *   此時(shí)勺届,a對(duì)象的objc成員變量仍持有一個(gè)強(qiáng)引用到對(duì)象b
 *   于是發(fā)生內(nèi)存泄露
 */

如何解決驶俊?于是我們引用一個(gè)__weakownership qualifier,被它修飾的變量都不持有對(duì)象的所有權(quán)免姿,而且當(dāng)變量指向的對(duì)象的RC為0時(shí),變量設(shè)置為nil榕酒。例如:

__weak NSString *text = [[NSString alloc] initWithFormat:@"Sam Lau"];
NSLog(@"%@", text);

由于text變量被__weak修飾胚膊,text并不持有@"Sam Lau"對(duì)象的所有權(quán),@"Sam Lau"對(duì)象一創(chuàng)建就馬上被釋放想鹰,并且編譯器給出警告紊婉,所以打印結(jié)果為(null)。

所以辑舷,針對(duì)剛才的引用循環(huán)問(wèn)題喻犁,只需要將Test類的屬性objc設(shè)置weak修飾符,那么就能解決何缓。

@interface Test : NSObject

@property (weak, nonatomic) id objc;

@end

{
    Test *test1 = [Test new];        /* 對(duì)象a */
    /* test1有一個(gè)強(qiáng)引用到對(duì)象a */
    Test *test2 = [Test new];        /* 對(duì)象b */
    /* test2有一個(gè)強(qiáng)引用到對(duì)象b */
    test1.objc = test2;              /* 對(duì)象a的成員變量objc不持有對(duì)象b */
    test2.objc = test1;              /* 對(duì)象b的成員變量objc不持有對(duì)象a */
}
/*   當(dāng)變量test1超過(guò)它作用域時(shí)肢础,它指向a對(duì)象會(huì)自動(dòng)release
 *   當(dāng)變量test2超過(guò)它作用域時(shí),它指向b對(duì)象會(huì)自動(dòng)release
 */

__unsafe_unretained ownership qualifier

__unsafe_unretained ownership qualifier碌廓,正如名字所示传轰,它是不安全的。它跟__weak相似谷婆,被它修飾的變量都不持有對(duì)象的所有權(quán)慨蛙,但當(dāng)變量指向的對(duì)象的RC為0時(shí)辽聊,變量并不設(shè)置為nil,而是繼續(xù)保存對(duì)象的地址期贫;這樣的話跟匆,對(duì)象有可能已經(jīng)釋放,但繼續(xù)訪問(wèn)通砍,就會(huì)造成非法訪問(wèn)(Invalid Access)贾铝。例子如下:

__unsafe_unretained id obj0 = nil;

{

    id obj1 = [[NSObject alloc] init];     // 對(duì)象A

    /* 由于obj1是強(qiáng)引用,所以obj1持有對(duì)象A的所有權(quán)埠帕,對(duì)象A的RC=1 */

    obj0 = obj1;
    /* 由于obj0是__unsafe_unretained垢揩,它不持有對(duì)象A的所有權(quán),但能夠引用它敛瓷,對(duì)象A的RC=1 */
    NSLog(@"A: %@", obj0);
}
/* 當(dāng)obj1超過(guò)它的作用域時(shí)叁巨,它指向的對(duì)象A將會(huì)自動(dòng)釋放 */
NSLog(@"B: %@", obj0);
/* 由于obj0是__unsafe_unretained,當(dāng)它指向的對(duì)象RC=0時(shí)呐籽,它會(huì)繼續(xù)保存對(duì)象的地址锋勺,所以兩個(gè)地址相同 */

打印結(jié)果是內(nèi)存地址相同:

如果將__unsafe_unretained改為weak的話,兩個(gè)打印結(jié)果將不同

__weak id obj0 = nil;

{

    id obj1 = [[NSObject alloc] init];     // 對(duì)象A

    /* 由于obj1是強(qiáng)引用狡蝶,所以obj1持有對(duì)象A的所有權(quán)庶橱,對(duì)象A的RC=1 */

    obj0 = obj1;
    /* 由于obj0是__unsafe_unretained,它不持有對(duì)象A的所有權(quán)贪惹,但能夠引用它苏章,對(duì)象A的RC=1 */
    NSLog(@"A: %@", obj0);
}
/* 當(dāng)obj1超過(guò)它的作用域時(shí),它指向的對(duì)象A將會(huì)自動(dòng)釋放 */
NSLog(@"B: %@", obj0);
/* 由于obj0是__weak奏瞬, 當(dāng)它指向的對(duì)象RC=0時(shí)枫绅,它會(huì)自動(dòng)設(shè)置為nil,所以兩個(gè)打印結(jié)果將不同*/

__autoreleasing ownership qualifier

引入ARC之后硼端,讓我們看看autorelease pool有哪些變化并淋。沒(méi)有ARC之前的寫法如下:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// put object into pool
id obj = [[NSObject alloc] init];
[obj autorelease];
[pool drain];
/* 超過(guò)autorelease pool作用域范圍時(shí),obj會(huì)自動(dòng)調(diào)用release方法 */

引入ARC之后珍昨,寫法比之前更加簡(jiǎn)潔:

@autoreleasepool {

    id __autoreleasing obj = [[NSObject alloc] init];
}

相比之前的創(chuàng)建县耽、使用和釋放NSAutoreleasePool對(duì)象,現(xiàn)在你只需要將代碼放在@autoreleasepool塊即可镣典。你也不需要調(diào)用autorelease方法了兔毙,只需要用__autoreleasing修飾變量即可。

1455700240202950.png

引用Pro Multithreading and Memory Management for iOS and OS X的圖

但是我們很少或基本上不使用autorelease pool骆撇。當(dāng)我們使用XCode創(chuàng)建工程后瞒御,有一個(gè)app的入口文件main.m使用了它:

int main(int argc, char * argv[]) {

    @autoreleasepool {

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

    }

}

roperty(屬性)

有了ARC之后,新的property modifier也被引入到Objective-C類的property神郊,例如:

@property (strong, nonatomic) NSString *text;

下面有張表來(lái)展示property modifier與ownership qualifier的對(duì)應(yīng)關(guān)系

1455700566330232.png

總結(jié)

要想掌握iOS/OS X的內(nèi)存管理肴裙,首先要深入理解引用計(jì)數(shù)(Reference Count)這個(gè)概念以及內(nèi)存管理的規(guī)則趾唱;在沒(méi)引入ARC之前,我們都是通過(guò)retain和release方法來(lái)手動(dòng)管理內(nèi)存蜻懦,但引入ARC之后甜癞,我們可以借助編譯器來(lái)幫忙自動(dòng)調(diào)用retain和release方法來(lái)簡(jiǎn)化內(nèi)存管理和減低出錯(cuò)的可能性。雖然__strong修飾符能夠執(zhí)行大多數(shù)內(nèi)存管理宛乃,但它不能解決引用循環(huán)(Reference Cycle)問(wèn)題悠咱,于是又引入另一個(gè)修飾符__weak。被__strong修飾的變量都持有對(duì)象的所有權(quán)征炼,而被__weak修飾的變量并不持有對(duì)象所有權(quán)析既。下篇我們介紹使用工具如何解決常見(jiàn)內(nèi)存問(wèn)題:懸掛指針和內(nèi)存泄露。

軟件運(yùn)行時(shí)會(huì)分配和使用設(shè)備的內(nèi)存資源谆奥,因此眼坏,在軟件開(kāi)發(fā)的過(guò)程中,需要進(jìn)行內(nèi)存管理酸些,以保證高效宰译、快速的分配內(nèi)存,并且在適當(dāng)?shù)臅r(shí)候釋放和回收內(nèi)存資源魄懂。
一沿侈、Objective-C內(nèi)存管理的對(duì)象
IOS開(kāi)發(fā)中,內(nèi)存中的對(duì)象主要有兩類市栗,一類是值類型缀拭,比如int、float肃廓、struct等基本數(shù)據(jù)類型智厌,另一類是引用類型,也就是繼承自NSObject類的所有的OC對(duì)象盲赊。前一種值類型不需要我們管理,后一種引用類型是需要我們管理內(nèi)存的敷扫,一旦管理不好哀蘑,就會(huì)產(chǎn)生非常糟糕的后果。
為什么值類型不需要管理葵第,而引用類型需要管理呢绘迁?那是因?yàn)樗麄兎峙鋬?nèi)存方式不一樣。
值類型會(huì)被放入棧中卒密,他們依次緊密排列缀台,在內(nèi)存中占有一塊連續(xù)的內(nèi)存空間,遵循先進(jìn)后出的原則哮奇。引用類型會(huì)被放到堆中膛腐,當(dāng)給對(duì)象分配內(nèi)存空間時(shí)睛约,會(huì)隨機(jī)的從內(nèi)存當(dāng)中開(kāi)辟空間,對(duì)象與對(duì)象之間可能會(huì)留有不確定大小的空白空間哲身,因此會(huì)產(chǎn)生很多內(nèi)存碎片辩涝,需要我們管理。
棧內(nèi)存與堆內(nèi)存從性能上比較勘天,棧內(nèi)存要優(yōu)于堆內(nèi)存怔揩,這是因?yàn)闂W裱冗M(jìn)后出的原則,因此當(dāng)數(shù)據(jù)量過(guò)大時(shí)脯丝,存入棧會(huì)明顯的降低性能商膊。因此,我們會(huì)把大量的數(shù)據(jù)存入堆中宠进,然后棧中存放堆的地址晕拆,當(dāng)需要調(diào)用數(shù)據(jù)時(shí),就可以快速的通過(guò)棧內(nèi)的地址找到堆中的數(shù)據(jù)砰苍。
值類型和引用類型之間是可以相互轉(zhuǎn)化的潦匈,把值類型轉(zhuǎn)化為引用類型的過(guò)程叫做裝箱,比如把int包裝為NSNumber赚导,這個(gè)過(guò)程會(huì)增加程序的運(yùn)行時(shí)間茬缩,降低性能。而把引用類型轉(zhuǎn)為值類型的過(guò)程叫做拆箱吼旧,比如把NSNumer轉(zhuǎn)為float凰锡,在拆箱的過(guò)程中,我們一定要注意數(shù)據(jù)原有的類型圈暗,如果類型錯(cuò)誤掂为,可能導(dǎo)致拆箱失敗,因此會(huì)存在安全性的問(wèn)題员串。手動(dòng)的拆箱和裝箱勇哗,都會(huì)增加程序的運(yùn)行時(shí)間,降低代碼可讀性寸齐,影響性能欲诺。
在IOS開(kāi)發(fā)過(guò)程中,棧內(nèi)存中的值類型系統(tǒng)會(huì)自動(dòng)管理渺鹦,堆內(nèi)存中的引用類型是需要我們管理的扰法。每個(gè)OC對(duì)象內(nèi)部都專門有四個(gè)字節(jié)來(lái)存儲(chǔ)引用計(jì)數(shù)器,它是一個(gè)整數(shù)毅厚,表示對(duì)象被引用的次數(shù)塞颁,通過(guò)它可以判斷對(duì)象是否被回收,如果引用計(jì)數(shù)為0,對(duì)象回收祠锣,不為0不回收酷窥。當(dāng)對(duì)象執(zhí)行alloc、new或者retain時(shí)锤岸,引用計(jì)數(shù)加1竖幔,release時(shí),引用計(jì)數(shù)減1是偷。
二拳氢、Objective-C管理內(nèi)存的方式
Objective-c中提供了兩種內(nèi)存管理機(jī)制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),分別提供對(duì)內(nèi)存的手動(dòng)和自動(dòng)管理蛋铆,來(lái)滿足不同的需求馋评。

1.MRC(人工引用計(jì)數(shù)),手動(dòng)管理內(nèi)存刺啦。
MRC模式下留特,所有的對(duì)象都需要手動(dòng)的添加retain、release代碼來(lái)管理內(nèi)存玛瘸。使用MRC蜕青,需要遵守誰(shuí)創(chuàng)建,誰(shuí)回收的原則糊渊。也就是誰(shuí)alloc右核,誰(shuí)release;誰(shuí)retain渺绒,誰(shuí)release贺喝。
當(dāng)引用計(jì)數(shù)為0的時(shí)候,必須回收宗兼,引用計(jì)數(shù)不為0躏鱼,不能回收,如果引用計(jì)數(shù)為0殷绍,但是沒(méi)有回收染苛,會(huì)造成內(nèi)存泄露。如果引用計(jì)數(shù)為0主到,繼續(xù)釋放殖侵,會(huì)造成野指針。為了避免出現(xiàn)野指針镰烧,我們?cè)卺尫诺臅r(shí)候,會(huì)先讓指針=nil楞陷。
2.ARC(自動(dòng)引用計(jì)數(shù))怔鳖,自動(dòng)管理內(nèi)存。
ARC是IOS5推出的新功能固蛾,通過(guò)ARC结执,可以自動(dòng)的管理內(nèi)存度陆。在ARC模式下,只要沒(méi)有強(qiáng)指針(強(qiáng)引用)指向?qū)ο笙揍#瑢?duì)象就會(huì)被釋放懂傀。在ARC模式下,不允許使用retain蜡感、release蹬蚁、retainCount等方法。并且郑兴,如果使用dealloc方法時(shí)犀斋,不允許調(diào)用[super dealloc]方法。
ARC模式下的property變量修飾詞為strong情连、weak叽粹,相當(dāng)于MRC模式下的retain、assign却舀。strong :代替retain虫几,缺省關(guān)鍵詞,代表強(qiáng)引用挽拔。weak:代替assign辆脸,聲明了一個(gè)可以自動(dòng)設(shè)置nil的弱引用,但是比assign多一個(gè)功能篱昔,指針指向的地址被釋放之后每强,指針本身也會(huì)自動(dòng)被釋放。
三州刽、與內(nèi)存有關(guān)的修飾符
strong :強(qiáng)引用空执,ARC中使用,與MRC中retain類似穗椅,使用之后辨绊,計(jì)數(shù)器+1。
weak :弱引用 匹表,ARC中使用门坷,如果只想的對(duì)象被釋放了,其指向nil袍镀,可以有效的避免野指針默蚌,其引用計(jì)數(shù)為1。
readwrite : 可讀可寫特性苇羡,需要生成getter方法和setter方法時(shí)使用绸吸。
readonly : 只讀特性,只會(huì)生成getter方法 不會(huì)生成setter方法,不希望屬性在類外改變锦茁。
assign :賦值特性攘轩,不涉及引用計(jì)數(shù),弱引用码俩,setter方法將傳入?yún)?shù)賦值給實(shí)例變量度帮,僅設(shè)置變量時(shí)使用。
retain :表示持有特性稿存,setter方法將傳入?yún)?shù)先保留笨篷,再賦值,傳入?yún)?shù)的retaincount會(huì)+1挠铲。
copy :表示拷貝特性冕屯,setter方法將傳入對(duì)象復(fù)制一份,需要完全一份新的變量時(shí)拂苹。
nonatomic :非原子操作安聘,不加同步,多線程訪問(wèn)可提高性能瓢棒,但是線程不安全的浴韭。決定編譯器生成的setter getter是否是原子操作。
atomic :原子操作脯宿,同步的念颈,表示多線程安全,與nonatomic相反连霉。

四榴芳、MRC與ARC混編
MRC與ARC理論上是不能兼容的,也就是你如果創(chuàng)建的項(xiàng)目是ARC模式的跺撼,在你的代碼中是不能使用release窟感,否則會(huì)出現(xiàn)內(nèi)存問(wèn)題。現(xiàn)在大部分程序都會(huì)選擇ARC的方式歉井,但是很多第三方的框架是MRC模式柿祈,如果想把這些第三方的文件加到自己項(xiàng)目中,需要進(jìn)行標(biāo)識(shí)哩至,否則編譯的時(shí)候會(huì)出現(xiàn)錯(cuò)誤躏嚎。
在ARC的項(xiàng)目中,對(duì)MRC的文件可以添加編譯選項(xiàng)-fno-objc-arc的標(biāo)識(shí)菩貌;在MRC的項(xiàng)目中卢佣,對(duì)ARC的文件可以添加編譯選項(xiàng) -fobjc-arc的標(biāo)識(shí)。

把MRC文件轉(zhuǎn)為ARC箭阶,實(shí)際上是去掉文件中的retain珠漂、release晚缩,

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市媳危,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冈敛,老刑警劉巖待笑,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抓谴,居然都是意外死亡暮蹂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門癌压,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)仰泻,“玉大人,你說(shuō)我怎么就攤上這事滩届〖睿” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵帜消,是天一觀的道長(zhǎng)棠枉。 經(jīng)常有香客問(wèn)我,道長(zhǎng)泡挺,這世上最難降的妖魔是什么辈讶? 我笑而不...
    開(kāi)封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮娄猫,結(jié)果婚禮上贱除,老公的妹妹穿的比我還像新娘。我一直安慰自己媳溺,他們只是感情好月幌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著褂删,像睡著了一般飞醉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上屯阀,一...
    開(kāi)封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天缅帘,我揣著相機(jī)與錄音,去河邊找鬼难衰。 笑死钦无,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的盖袭。 我是一名探鬼主播失暂,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼彼宠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了弟塞?” 一聲冷哼從身側(cè)響起凭峡,我...
    開(kāi)封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎决记,沒(méi)想到半個(gè)月后摧冀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡系宫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年索昂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扩借。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡椒惨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出潮罪,到底是詐尸還是另有隱情康谆,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布错洁,位于F島的核電站秉宿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏屯碴。R本人自食惡果不足惜描睦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望导而。 院中可真熱鬧忱叭,春花似錦、人聲如沸今艺。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)虚缎。三九已至撵彻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間实牡,已是汗流浹背陌僵。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留创坞,地道東北人碗短。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像题涨,于是被迫代替她去往敵國(guó)和親偎谁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子总滩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

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

  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制。與retain配對(duì)使用的方法是dealloc還是release巡雨,為什么闰渔?需要與a...
    丶逐漸閱讀 1,965評(píng)論 1 16
  • 29.理解引用計(jì)數(shù) Objective-C語(yǔ)言使用引用計(jì)數(shù)來(lái)管理內(nèi)存,也就是說(shuō)鸯隅,每個(gè)對(duì)象都有個(gè)可以遞增或遞減的計(jì)數(shù)...
    Code_Ninja閱讀 1,492評(píng)論 1 3
  • 內(nèi)存管理 ARC處理原理 ARC是Objective-C編譯器的特性澜建,而不是運(yùn)行時(shí)特性或者垃圾回收機(jī)制,ARC所做...
    b485c88ab697閱讀 11,207評(píng)論 3 47
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時(shí)分配內(nèi)存(比如創(chuàng)建一個(gè)對(duì)象,會(huì)增加內(nèi)存占用)與...
    蚊香醬閱讀 5,723評(píng)論 8 119
  • Guiyang--a developing and green city Located in the south...
    乾之閱讀 146評(píng)論 0 0