iOS中的GC垃圾回收機(jī)制與內(nèi)存管理機(jī)制

問題: NSArray和NSMutableArray在Copy和MutableCopy下的內(nèi)存是怎樣的港庄?深拷貝和淺拷貝的區(qū)別? 有兩種情況:淺拷貝和深拷貝。

淺拷貝只是復(fù)制了內(nèi)存地址,也就是對內(nèi)存空間的引用;

深拷貝是開辟新的空間并復(fù)制原空間相同的內(nèi)容灰伟,新指針指向新空間內(nèi)容。

除了NSArray在Copy下是淺復(fù)制儒旬,其他都是深復(fù)制栏账。

    // 不可變數(shù)組
    NSArray *oldArray = @[@1, @2, @3];
    NSArray *newArray;
    // 可變數(shù)組
    NSMutableArray *oldMulArray = [[NSMutableArray alloc]initWithArray:oldArray];
    NSMutableArray *newMulArray;
    
    newArray = [oldArray copy];               // 淺拷貝
    newArray = [oldArray mutableCopy];        // 深拷貝
    newMulArray = [oldMulArray copy];         // 深拷貝
    newMulArray = [oldMulArray mutableCopy];  // 深拷貝

問題: MRC中通過調(diào)用靜態(tài)方法創(chuàng)建的新對象,不再使用時需要對其發(fā)送release消息嗎义矛?

不需要发笔,因為約定靜態(tài)方法創(chuàng)建的對象會自動將其放入自動釋放池,即已對其發(fā)送autorelease消息凉翻,因此不可再對其進(jìn)行手動釋放了讨。MRC中靜態(tài)方法創(chuàng)建新對象的實現(xiàn)模板如下:

/** * 靜態(tài)構(gòu)造函數(shù) */
+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age;

+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age {
    Person *person = [[[Person alloc] init] autorelease];
    person.name = name;
    person.age = age;
    return person;
}

問題: BAD_ACCESS在什么情況下出現(xiàn)?
BAD_ACCESS報錯屬于內(nèi)存錯誤制轰,會導(dǎo)致程序崩潰前计,錯誤的原因是訪問了野指針(懸掛指針)。野指針指的是本來指針指向的對象已經(jīng)釋放了垃杖,但指向該對象的指針沒有置nil男杈,程序還以為該指針指向那個對象,導(dǎo)致存在一些潛在的危險訪問操作调俘,這些危險訪問操作就會導(dǎo)致BAD_ACCESS錯誤造成程序崩潰伶棒。訪問的含義包括多種情況,例如:向野指針發(fā)送消息彩库,讀寫野指針本來指向的對象的成員變量等等肤无。 ***

問題: 在block內(nèi)如何修改block外部變量?
在block內(nèi)部修改block外部變量會編譯不通過骇钦,提示變量缺少__block修飾宛渐,不可賦值。要想在block內(nèi)部修改block外部變量,則必須在外部定義變量時窥翩,前面加上__block修飾符:

/* block外部變量 */
__block int var1 = 0;
int var2 = 0;
/* 定義block */
void (^block)(void) = ^{
    /* 試圖修改block外部變量 */
    var1 = 100;
    /* 編譯錯誤业岁,在block內(nèi)部不可對var2賦值 */
    // var2 = 1;
};
/* 執(zhí)行block */
block();
NSLog(@"修改后的var1:%d",var1); // 修改后的var1:100

問題: 使用block時什么情況會發(fā)生引用循環(huán),如何解決寇蚊?
常見的使用block引起引用循環(huán)的情況為:在一個對象中強(qiáng)引用了一個block笔时,在該block中又強(qiáng)引用了該對象,此時就出現(xiàn)了該對象和該block的循環(huán)引用幔荒,例如:

/* Test.h */
#import <Foundation/Foundation.h> /* 聲明一個名為MYBlock的block糊闽,參數(shù)為空梳玫,返回值為void */
typedef void (^MYBlock)();

@interface Test : NSObject
/* 定義并強(qiáng)引用一個MYBlock */
@property (nonatomic, strong) MYBlock block;
/* 對象屬性 */
@property (nonatomic, copy) NSString *name;

- (void)print;

@end

/* Test.m */
#import "Test.h" @implementation Test

- (void)print {
    self.block = ^{
        NSLog(@"%@",self.name);
    };
    self.block();
}

@end

解決上面的引用循環(huán)的方法一個是強(qiáng)制將一方置nil爹梁,破壞引用循環(huán),另外一種方法是將對象使用__weak或者_(dá)_block修飾符修飾之后再在block中使用(注意是在ARC下):

- (void)print {
    __weak typeof(self) weakSelf = self;
    self.block = ^{
        NSLog(@"%@",weakSelf.name);
    };
    self.block();
}

問題: 下面代碼有什么問題提澎?如何修改姚垃?

#import "TTAppDelegate.h" 
@interface TTParent : NSObject

@property (atomic) NSMutableArray *children;

@end

@implementation TTParent
@end

@interface TTChild : NSObject

@property (atomic) TTParent *parent;

@end

@implementation TTChild
@end

@implementation TTAppDelegate

- (BOOL)application:(UIApplication *)application
  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    TTParent *parent = [[TTParent alloc] init];
    parent.children = [[NSMutableArray alloc] init];
    for (int i = 0; i < 10; i++) {
        TTChild *child = [[TTChild alloc] init];
        child.parent = parent;
        [parent.children addObject:child];
    }
    return YES;
}
@end

這是一個很明顯的“循環(huán)引用”問題,parent持有children數(shù)組盼忌,數(shù)組持有每一個child积糯,每個child又持有parent,這樣即使外部的所有引用都釋放了谦纱,由于這個引用循環(huán)看成,parent的引用計數(shù)將永遠(yuǎn)大于0永遠(yuǎn)無法被釋放。

解決方法很簡單跨嘉,將child對parent的引用改為weak弱引用即可川慌,這樣child對parent的弱引用不會導(dǎo)致parent的引用計數(shù)增加,且parent釋放后祠乃,weak修飾的對parent引用的指針會自動置nil梦重。

問題:僵尸對象、野指針亮瓷、空指針分別指什么琴拧,有什么區(qū)別?

僵尸對象:一個OC對象引用計數(shù)為0被釋放后就變成僵尸對象了嘱支,僵尸對象的內(nèi)存已經(jīng)被系統(tǒng)回收蚓胸,雖然可能該對象還存在,數(shù)據(jù)依然在內(nèi)存中除师,但僵尸對象已經(jīng)是不穩(wěn)定對象了沛膳,不可以再訪問或者使用,它的內(nèi)存是隨時可能被別的對象申請而占用的馍盟;

野指針:野指針出現(xiàn)的原因是指針沒有賦值于置,或者指針指向的對象已經(jīng)被釋放掉了,野指針指向一塊隨機(jī)的垃圾內(nèi)存,向他們發(fā)送消息會報EXC_BAD_ACCESS錯誤導(dǎo)致程序崩潰八毯;

空指針:空指針不同于野指針搓侄,它是一個沒有指向任何東西的指針,空指針是有效指針话速,值為nil讶踪、NULL、Nil或0等泊交,給空指針發(fā)送消息不會報錯乳讥,只是不響應(yīng)消息而已,應(yīng)該給野指針及時賦予零值變成有效的空指針廓俭,避免內(nèi)存報錯云石。 ***

問題: Objective-C有GC垃圾回收機(jī)制嗎?

GC(Garbage Collection)研乒,垃圾回收機(jī)制汹忠,簡單地說就是程序中及時處理廢棄不用的內(nèi)存對象的機(jī)制,防止內(nèi)存中廢棄對象堆積過多造成內(nèi)存泄漏雹熬。Objective-C語言本身是支持垃圾回收機(jī)制的宽菜,但有平臺局限性,僅限于Mac桌面系統(tǒng)開發(fā)中竿报,而在iPhone和iPad等蘋果移動終端設(shè)備中是不支持垃圾回收機(jī)制的铅乡。在移動設(shè)備開發(fā)中的內(nèi)存管理是采用MRC(Manual Reference Counting)以及iOS5以后的ARC(Automatic Reference Counting),本質(zhì)都是RC引用計數(shù)烈菌,通過引用計數(shù)的方式來管理內(nèi)存的分配與釋放阵幸,從而防止內(nèi)存泄漏。

另外引用計數(shù)RC和垃圾回收GC是有區(qū)別的僧界。垃圾回收是宏觀的侨嘀,對整體進(jìn)行內(nèi)存管理,雖然不同平臺垃圾回收機(jī)制有異捂襟,但基本原理都是一樣的:將所有對象看做一個集合咬腕,然后在GC循環(huán)中定時檢測活動對象和非活動對象,及時將用不到的非活動對象釋放掉來避免內(nèi)存泄漏葬荷,也就是說用不到的垃圾對象是交給GC來管理釋放的涨共,而無需開發(fā)者關(guān)心,典型的是Java中的垃圾回收機(jī)制宠漩;相比于GC举反,引用計數(shù)是局部性的,開發(fā)者要管理控制每個對象的引用計數(shù)扒吁,單個對象引用計數(shù)為0后會馬上被釋放掉火鼻。ARC自動引用計數(shù)則是一種改進(jìn),由編譯器幫助開發(fā)者自動管理控制引用計數(shù)(自動在合適的時機(jī)發(fā)送release和retain消息)。另外自動釋放池autorelease pool則像是一個局部的垃圾回收魁索,將部分垃圾對象集中釋放融撞,相對于單個釋放會有一定延遲。

相關(guān)問題: 自動釋放池跟GC(垃圾回收)有什么區(qū)別粗蔚?iPhone上有GC么尝偎?[pool release]和[pool drain]有什么區(qū)別?

[pool release]和[pool drain]在作用上是一樣的鹏控,都是傾倒自動釋放池致扯,區(qū)別是drain在支持GC垃圾回收的系統(tǒng)中(Mac系統(tǒng))可以引起GC回收操作,而release不可以当辐。對于自動釋放池一般還是使用[pool drain]了抖僵,一是它的功能對系統(tǒng)兼容性更強(qiáng),二者也是為了跟普通對象的release釋放區(qū)別開瀑构。自動釋放池的釋放操作指的是向池內(nèi)所有的對象發(fā)送release消息裆针,以讓系統(tǒng)及時釋放池內(nèi)的所有對象。 ***

問題: 如果一個對象釋放前被加到了NotificationCenter中寺晌,不在NotificationCenter中remove這個對象可能會出現(xiàn)什么問題?

首先對于NotificationCenter的使用澡刹,我們都知道呻征,只要添加對象到消息中心進(jìn)行通知注冊,之后就一定要對其remove進(jìn)行通知注銷罢浇。將對象添加到消息中心后陆赋,消息中心只是保存該對象的地址,消息中心到時候會根據(jù)地址發(fā)送通知給該對象嚷闭,但并沒有取得該對象的強(qiáng)引用攒岛,對象的引用計數(shù)不會加1。如果對象釋放后卻沒有從消息中心remove掉進(jìn)行通知注銷胞锰,也就是通知中心還保存著那個指針灾锯,而那個指針指的對象可能已經(jīng)被釋放銷毀了,那個指針就成為一個野指針嗅榕,當(dāng)通知發(fā)生時顺饮,會向這個野指針發(fā)送消息導(dǎo)致程序崩潰。 ***

問題: Objective-C是如何實現(xiàn)內(nèi)存管理的凌那?autorealease pool自動釋放池是什么兼雄?autorelease的對象是在什么時候被release的?autorelease和release有什么區(qū)別帽蝶?

Objective-C的內(nèi)存管理本質(zhì)上是通過引用計數(shù)實現(xiàn)的赦肋,每次RunLoop都會檢查對象的引用計數(shù),如果引用計數(shù)為0,說明該對象已經(jīng)沒人用了佃乘,可以對其進(jìn)行釋放了局蚀。其中引用計數(shù)可以大體分為三種:MRC(手動內(nèi)存計數(shù))、ARC(自動內(nèi)存計數(shù)恕稠,iOS5以后)和內(nèi)存池琅绅。

其中引用計數(shù)是如何操作的呢?不論哪種引用計數(shù)方式鹅巍,本質(zhì)都是在合適的時機(jī)將對象的引用計數(shù)加1或者減1千扶。

這里簡單歸結(jié)一下:
使對象引用計數(shù)加1的常見操作有:alloc、copy骆捧、retain
使對象引用計數(shù)減1的常見操作有:release澎羞、autorealease

自動釋放池

自動釋放池釋放的時機(jī),也就是自動釋放池內(nèi)的所有對象是在什么時候釋放的敛苇,這里要提到程序的運(yùn)行周期RunLoop妆绞。對于每一個新的RunLoop,系統(tǒng)都會隱式的創(chuàng)建一個autorelease pool枫攀,RunLoop結(jié)束時自動釋放池便會進(jìn)行對象釋放操作括饶。 autorelease和release的區(qū)別主要是引用計數(shù)減一的時機(jī)不同,autorelease會在對象的使用真正結(jié)束的時候才做引用計數(shù)減1,而不是收到消息立馬釋放来涨。

retain图焰、release和autorelease的底層實現(xiàn)

最后通過了解這三者的較底層實現(xiàn)來理解它們的本質(zhì)區(qū)別:

-(id)retain {
    /* 對象引用計數(shù)加1 */
    NSIncrementExtraRefCount(self);
    return self;
}

-(void)release {
    /* 對象引用計數(shù)減1,之后如果引用計數(shù)為0則釋放 */
    if(NSDecrementExtraRefCountWasZero(self)) {
        NSDeallocateObject(self);
    }
}

-(id)autorelease {
    /* 添加對象到自動釋放池 */
    [NSAutoreleasePool addObject:self];
    return self;
}

問題: 為什么很多內(nèi)置的類蹦掐,如TableViewController的delegate的屬性是assign不是retain?
delegate代理的屬性通常設(shè)置為assign或者weak是為了避免循環(huán)引用技羔,所有的引用計數(shù)系統(tǒng),都存在循環(huán)引用的問題卧抗,但也有個別特殊情況藤滥,個別類的代理例如CAAnimation的delegate就是使用strong強(qiáng)引用。

其他問法: 委托的property聲明用什么屬性社裆?為什么拙绊? * **問題: CAAnimation的delegate代理是強(qiáng)引用還是弱引用?

CAAnimation的代理是強(qiáng)引用浦马,是內(nèi)存管理中的其中一個罕見的特例时呀。我們知道為了避免循環(huán)引用問題,delegate代理一般都使用weak修飾表示弱引用的晶默,而CAAnimation動畫是異步的谨娜,如果動畫的代理是弱應(yīng)用不是強(qiáng)應(yīng)用的話,會導(dǎo)致其隨時都可能被釋放掉磺陡。在使用動畫時要注意采取措施避免循環(huán)引用趴梢,例如及時在視圖移除之前的合適時機(jī)移除動畫漠畜。

CAAnimation的代理定義如下,明確說了動畫的代理在動畫對象整個生命周期間是被強(qiáng)引用的坞靶,默認(rèn)為nil憔狞。

/* The delegate of the animation. This object is retained for the * lifetime of the animation object. Defaults to nil. See below for the * supported delegate methods. */

@property(nullable, strong) id <CAAnimationDelegate> delegate;

問題: OC中,與alloc語義相反的方法是dealloc還是release彰阴?與retain語義相反的方法是dealloc還是release瘾敢?需要與alloc配對使用的方法是dealloc還是release,為什么尿这?

alloc與dealloc語意相反簇抵,alloc是創(chuàng)建變量,dealloc是釋放變量射众;

retain與release語義相反碟摆,retain保留一個對象,調(diào)用后使變量的引用計數(shù)加1叨橱,而release釋放一個對象典蜕,調(diào)用后使變量的引用計數(shù)減1。

雖然alloc對應(yīng)dealloc罗洗,retain對應(yīng)release愉舔,但是與alloc配對使用的方法是release,而不是dealloc栖博。為什么呢屑宠?這要從他們的實際效果來看。事實上alloc和release配對使用只是表象仇让,本質(zhì)上其實還是retain和release的配對使用。alloc用來創(chuàng)建對象躺翻,剛創(chuàng)建的對象默認(rèn)引用計數(shù)為1丧叽,相當(dāng)于調(diào)用alloc創(chuàng)建對象過程中同時會調(diào)用一次retain使對象引用計數(shù)加1,自然要有對應(yīng)的release的一次調(diào)用公你,使對象在不用時能夠被釋放掉防止內(nèi)存泄漏踊淳。

此外,dealloc是在對象引用計數(shù)為0以后系統(tǒng)自動調(diào)用的陕靠,dealloc沒有使對象引用計數(shù)減1的作用迂尝,只是在對象引用計數(shù)為0后被系統(tǒng)調(diào)用進(jìn)行內(nèi)存回收的收尾工作。

問題: 以下每行代碼執(zhí)行后剪芥,person對象的retain count分別是多少

Person *person = [[Person alloc] init];
[person retain];
[person release];
[person release];

1-2-1-0垄开。開始alloc創(chuàng)建對象并持有對象,初始引用計數(shù)為1税肪,retain一次引用計數(shù)加1變?yōu)?溉躲,之后release對象兩次榜田,引用計數(shù)減1兩次,先后變?yōu)?锻梳、0箭券。 ***

問題:執(zhí)行下面的代碼會發(fā)生什么后果? Ball *ball = [[[[Ball alloc] init] autorelease] autorelease];

\程序會因其而崩潰疑枯,因為對象被加入到自動釋放池兩次辩块,當(dāng)對象被移除時,自動釋放池將其釋放了不止一次荆永,其中第二次釋放必定導(dǎo)致崩潰废亭。

問題: 內(nèi)存管理的幾條原則是什么?按照默認(rèn)法則屁魏,哪些關(guān)鍵字生成的對象需要手動釋放滔以?哪些對象不需要手動釋放會自動進(jìn)入釋放池?在和property結(jié)合的時候怎樣有效的避免內(nèi)存泄露氓拼?

起初MRC中開發(fā)者要自己手動管理內(nèi)存你画,基本原則是:誰創(chuàng)建,誰釋放桃漾,誰引用坏匪,誰管理。其中創(chuàng)建主要始于關(guān)鍵詞new撬统、alloc和copy的使用适滓,創(chuàng)建并持有開始引用計數(shù)為1,如果引用要通過發(fā)送retain消息增加引用計數(shù)恋追,通過發(fā)送release消息減少引用計數(shù)凭迹,引用計數(shù)為0后對象會被系統(tǒng)清理釋放。現(xiàn)在有了ARC后編譯器會自動管理引用計數(shù)苦囱,開發(fā)者不再需要也不可以再手動顯示管理引用計數(shù)嗅绸。

當(dāng)使用new、alloc或copy方法創(chuàng)建一個對象時撕彤,該對象引用計數(shù)器為1鱼鸠。不再需要使用該對象時可以向其發(fā)送release或autorelease消息,在其使用完畢時被系統(tǒng)釋放羹铅。如果retain了某個對象蚀狰,需要對應(yīng)release或autorelease該對象,保持retain方法和release方法使用次數(shù)相等职员。

使用new麻蹋、alloc、copy關(guān)鍵字生成的對象和retain了的對象需要手動釋放廉邑。設(shè)置為autorelease的對象不需要手動釋放哥蔚,會直接進(jìn)入自動釋放池倒谷。

下面代碼的輸出依次為:

    NSMutableArray* ary = [[NSMutableArray array] retain];
    NSString *str = [NSString stringWithFormat:@"test"];
    [str retain];
    [ary addObject:str];
    NSLog(@"%@%d",str,[str retainCount]);
    [str retain];
    [str release];
    [str release];
    NSLog(@"%@%d",str,[str retainCount]);
    [ary removeAllObjects];
    NSLog(@"%@%d",str,[str retainCount]);

2,3糙箍,1
3渤愁,2,1(right)
1深夯,2抖格,3
2,1咕晋,3

此問題考查的是非MRC下引用計數(shù)的使用(只有在MRC下才可以通過retain和release關(guān)鍵字手動管理內(nèi)存對象雹拄,才可以向?qū)ο蟀l(fā)送retainCount消息獲取當(dāng)前引用計數(shù)的值),開始使用類方法stringWithFormat在堆上新創(chuàng)建了一個字符串對象str掌呜,str創(chuàng)建并持有該字符串對象默認(rèn)引用計數(shù)為1滓玖,之后retain使引用計數(shù)加1變?yōu)?,然后又動態(tài)添加到數(shù)組中且該過程同樣會讓其引用計數(shù)加1變?yōu)?(數(shù)組的add操作是添加對成員對象的強(qiáng)引用)质蕉,此時打印結(jié)果引用計數(shù)為3势篡;之后的三次操作使引用計數(shù)加1后又減2,變?yōu)?模暗,此時打印引用計數(shù)結(jié)果為2禁悠;最后數(shù)組清空成員對象,數(shù)組的remove操作會讓移除的對象引用計數(shù)減1兑宇,因此str的引用計數(shù)變?yōu)榱?碍侦,打印結(jié)果為1。因此先后引用計數(shù)的打印結(jié)果為:3隶糕,2瓷产,1。

這里要特別注意上面為何說stringWithFormat方法是在堆上創(chuàng)建的字符串對象枚驻,這里涉及到NSString的內(nèi)存管理惯豆,下面單獨(dú)對其進(jìn)行擴(kuò)展和分析征堪。 OC中常用的創(chuàng)建NSString字符串對象的方法主要有以下五種

    /* 字面量直接創(chuàng)建 */
    NSString *str1 = @"string";
    /* 類方法創(chuàng)建
    NSString *str2 = [NSString stringWithFormat:@"string"];
    NSString *str3 = [NSString stringWithString:@"string"]; // 編譯器優(yōu)化后棄用,效果等同于str1的字面量創(chuàng)建方式 */
    /* 實例方法創(chuàng)建 */
    NSString *str4 = [[NSString alloc] initWithFormat:@"string"];
    NSString *str5 = [[NSString alloc] initWithString:@"string"]; // 編譯器優(yōu)化后棄用系宜,效果等同于str1的字面量創(chuàng)建方式

開發(fā)中推薦的是前兩種str1和str2的創(chuàng)建方式灾常,分別用來創(chuàng)建不可變字符串和格式化字符串霎冯。最新的編譯器優(yōu)化后棄用了str3的stringWithString和str5的initWithString創(chuàng)建方式,現(xiàn)在這樣創(chuàng)建會報警告钞瀑,說這樣創(chuàng)建是多余的沈撞,因為實際效果和直接用字面量創(chuàng)建相同,也都是在常量內(nèi)存區(qū)創(chuàng)建一個不可變字符串雕什,由系統(tǒng)自動管理內(nèi)存和優(yōu)化內(nèi)存缠俺,他們創(chuàng)建后可以認(rèn)為已經(jīng)被autorelease了显晶。另外,此處由于字符串的內(nèi)容都是“string”壹士,使用str1磷雇、str3和str5創(chuàng)建的的字符串對象實際在常量內(nèi)存區(qū)只有一個備份,這是編譯器的優(yōu)化效果躏救,而str2和str4由于是在堆上創(chuàng)建因此各自有自己的備份唯笙。

此外最重要的是這五種方法創(chuàng)建的字符串對象所處的內(nèi)存類型,str1盒使、str3和str5都是創(chuàng)建的不可變字符串崩掘,是位于常量內(nèi)存區(qū)的,由系統(tǒng)管理內(nèi)存少办;stringWithFormat和initWithFormat創(chuàng)建的都是格式化的動態(tài)字符串對象苞慢,在堆上創(chuàng)建,需要手動管理內(nèi)存英妓。

相關(guān)問題:當(dāng)你用stringWithString來創(chuàng)建一個新NSString對象的時候挽放,你可以認(rèn)為:

這個新創(chuàng)建的字符串對象已經(jīng)被autorelease了(right)
這個新創(chuàng)建的字符串對象已經(jīng)被retain了
全都不對
這個新創(chuàng)建的字符串對象已經(jīng)被release了

問題:什么是安全釋放?
釋放掉不再使用的對象同時不會造成內(nèi)存泄漏或指針懸掛問題稱其為安全釋放鞋拟。 ***

問題: 這段代碼有什么問題,如何修改骂维?

for (int i = 0; i < someLargeNumber; i++) {
   NSString *string = @”Abc”;
   string = [string lowercaseString];
   string = [string stringByAppendingString:@"xyz"];
   NSLog(@“%@”, string);
}

代碼通過循環(huán)短時間內(nèi)創(chuàng)建了大量的NSString對象,在默認(rèn)的自動釋放池釋放之前這些對象無法被立即釋放贺纲,會占用大量內(nèi)存航闺,造成內(nèi)存高峰以致內(nèi)存不足。

為了防止大量對象堆積應(yīng)該在循環(huán)內(nèi)手動添加自動釋放池猴誊,這樣在每一次循環(huán)結(jié)束潦刃,循環(huán)內(nèi)的自動釋放池都會被自動釋放及時騰出內(nèi)存,從而大大縮短了循環(huán)內(nèi)對象的生命周期懈叹,避免內(nèi)存占用高峰乖杠。

代碼改進(jìn)方法是在循環(huán)內(nèi)部嵌套一個自動釋放池:

for (int i = 0; i < 1000000; i++) {
    @autoreleasepool {
        NSString *string = @"Abc";
        string = [string lowercaseString];
        string = [string stringByAppendingString:@"xyz"];
        NSLog(@"%@",string);
    }
}

相關(guān)問題: 這段代碼有什么問題?會不會造成內(nèi)存泄露(多線程)澄成?在內(nèi)存緊張的設(shè)備上做大循環(huán)時自動釋放池是寫在循環(huán)內(nèi)好還是循環(huán)外好胧洒?為什么?

for(int index = 0; index < 20; index++) {
    NSString *tempStr = @”tempStr”;
    NSLog(tempStr);
    NSNumber *tempNumber = [NSNumber numberWithInt:2];
    NSLog(tempNumber);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墨状,一起剝皮案震驚了整個濱河市卫漫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌肾砂,老刑警劉巖列赎,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镐确,居然都是意外死亡包吝,警方通過查閱死者的電腦和手機(jī)饼煞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诗越,“玉大人砖瞧,你說我怎么就攤上這事〔粲鳎” “怎么了芭届?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長感耙。 經(jīng)常有香客問我褂乍,道長,這世上最難降的妖魔是什么即硼? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任逃片,我火速辦了婚禮,結(jié)果婚禮上只酥,老公的妹妹穿的比我還像新娘褥实。我一直安慰自己,他們只是感情好裂允,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布损离。 她就那樣靜靜地躺著,像睡著了一般绝编。 火紅的嫁衣襯著肌膚如雪僻澎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天十饥,我揣著相機(jī)與錄音窟勃,去河邊找鬼。 笑死逗堵,一個胖子當(dāng)著我的面吹牛秉氧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜒秤,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼汁咏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了作媚?” 一聲冷哼從身側(cè)響起梆暖,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掂骏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厚掷,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡弟灼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年级解,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片田绑。...
    茶點(diǎn)故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡勤哗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掩驱,到底是詐尸還是另有隱情芒划,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布欧穴,位于F島的核電站民逼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏涮帘。R本人自食惡果不足惜拼苍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望调缨。 院中可真熱鬧疮鲫,春花似錦、人聲如沸弦叶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伤哺。三九已至燕侠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間默责,已是汗流浹背贬循。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桃序,地道東北人杖虾。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像媒熊,于是被迫代替她去往敵國和親奇适。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評論 2 355

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

  • 內(nèi)存管理 簡述OC中內(nèi)存管理機(jī)制芦鳍。與retain配對使用的方法是dealloc還是release嚷往,為什么?需要與a...
    丶逐漸閱讀 1,964評論 1 16
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,103評論 1 32
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時分配內(nèi)存(比如創(chuàng)建一個對象,會增加內(nèi)存占用)與...
    蚊香醬閱讀 5,723評論 8 119
  • 1. 內(nèi)總管理原則(引用計數(shù)) IOS的對象都繼承于NSObject, 該對象有一個方法:retainCount...
    lilinjianshu閱讀 2,158評論 0 2
  • 內(nèi)存管理是程序在運(yùn)行時分配內(nèi)存柠衅、使用內(nèi)存皮仁,并在程序完成時釋放內(nèi)存的過程。在Objective-C中,也被看作是在眾...
    蹲瓜閱讀 3,076評論 1 8