iOS面試復(fù)習(xí)1——內(nèi)存

一、內(nèi)存管理(MRC)

(一) 管理對(duì)象

管理對(duì)象:OC對(duì)象

原因:

? ? ? ? 1、OC對(duì)象存放于堆里面

? ? ? ? 2、非OC對(duì)象(int、char、float、double、struct、enum)一般放在棧里面(棧內(nèi)存會(huì)被系統(tǒng)自動(dòng)回收)


(二) 基本原理

1、每個(gè)OC對(duì)象內(nèi)部都有4個(gè)字節(jié)的存儲(chǔ)空間來(lái)存放引用計(jì)數(shù)器

2、誰(shuí)創(chuàng)建誰(shuí)release :如果你通過(guò)alloc、new或[mutable]copy來(lái)創(chuàng)建一個(gè)對(duì)象(引用計(jì)數(shù)+1),那么你必須調(diào)用release或autorelease(引用計(jì)數(shù)-1)

3、誰(shuí)retain誰(shuí)release:只要你調(diào)用了retain(引用計(jì)數(shù)+1),就必須調(diào)用一次release(引用計(jì)數(shù)-1)

4、release并不代表銷毀\回收對(duì)象,僅僅是計(jì)數(shù)器-1;引用計(jì)數(shù)為0時(shí),對(duì)象被銷毀,系統(tǒng)會(huì)自動(dòng)給對(duì)象發(fā)送一條dealloc消息。

5、一般來(lái)說(shuō),除了alloc、new或copy之外的方法創(chuàng)建的對(duì)象都被申明了autorelease。


(三) Set方法

- (void) setName:(NSString *)name

{

? ? ? ? if(_name!= name){

? ? ? ? ? ? ? ? [_namerelease];

? ? ? ? ? ? ? ? _name= [name retail];

? ? ? ? }

}


(四) ?一些術(shù)語(yǔ)

1、僵尸對(duì)象

已經(jīng)被銷毀的對(duì)象(不能再使用的對(duì)象)

2、野指針

指向僵尸對(duì)象(不可用內(nèi)存)的指針

給野指針發(fā)消息會(huì)報(bào)EXC_BAD_ACCESS錯(cuò)誤

3、空指針

沒(méi)有指向存儲(chǔ)空間的指針(里面存的是nil,也就是0)

給空指針發(fā)消息是沒(méi)有任何反應(yīng)的

objc_msgSend會(huì)通過(guò)判斷self來(lái)決定是否發(fā)送消息,如果self為nil,那么selector也會(huì)為空,直接返回,所以不會(huì)出現(xiàn)問(wèn)題。視方法返回值,向nil發(fā)消息可能會(huì)返回nil(返回值為對(duì)象)、0(返回值為一些基礎(chǔ)數(shù)據(jù)類型)或0X0(返回值為id)等。但是對(duì)[NSNull null]對(duì)象發(fā)送消息時(shí),是會(huì)crash的,因?yàn)檫@個(gè)NSNull類只有一個(gè)null方法


為了避免野指針錯(cuò)誤的常見(jiàn)辦法

在對(duì)象被銷毀之后,將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔?/p>


(五) 一些設(shè)置

1、關(guān)閉ARC功能

Building->AutoMatic Reference Counting->NO

2、開(kāi)啟僵尸對(duì)象監(jiān)控

Edit Scheme->Diagnostics->Enable Zombie Object


(六) NSString創(chuàng)建類的幾種方式

NSString類型的字符串有三種方法:

方法1.直接賦值:?? ??NSString?*str1=?@"my string";

方法2.類函數(shù)初始化生成: ? ??NSString?*str2= [NSString stringWithString:@"my string"];

方法3.實(shí)例方法初始化生成: NSString?*str3= [[NSString alloc] initWithString:@"my string"];

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?NSString?*str4?=[[NSString?alloc]initWithFormat:@"my string"];


區(qū)別1:方法一生成字符串時(shí),不會(huì)初始化內(nèi)存空間,所以使用結(jié)束后不用釋放內(nèi)存;

? ? ? ? ? 而其他三個(gè)都會(huì)初始化內(nèi)存空間,使用結(jié)束后要釋放內(nèi)存;

? ? ? ? ? 在釋放內(nèi)存時(shí)方法2和3也不同,方法2是autorelease類型,內(nèi)存由系統(tǒng)釋放;方法3則必須手動(dòng)釋放

區(qū)別2:用Format初始化的字符串,需要初始化一段動(dòng)態(tài)內(nèi)存空間,如:0x6a42a40;

? ? ? ? ? 而用String聲明的字符串,初始化的是常量?jī)?nèi)存區(qū),如:0x46a8,常量?jī)?nèi)存區(qū)的地址,只要值相同,占用的 ?地址空間是一致的。

所以str3和str1的地址一致,但是str4和str1的地址不一致。


二、內(nèi)存警告

(一)?app收到Memory Warning后會(huì)調(diào)用:

UIApplication::didReceiveMemoryWarning->

UIApplicationDelegate::applicationDidReceiveMemoryWarning,

然后調(diào)用當(dāng)前所有的viewController進(jìn)行處理。

因此處理的主要工作是在viewController。


(二) 當(dāng)我們的程序在第一次收到內(nèi)存不足警告時(shí),應(yīng)該釋放一些不用的資源,以節(jié)省部分內(nèi)存。否則,當(dāng)內(nèi)存不足情形依然存在,iOS再次向我們程序發(fā)出內(nèi)存不足的警告時(shí),我們的程序?qū)?huì)被iOS kill掉。

1、iOS3-iOS5.0以前版本收到內(nèi)存警告:

調(diào)用didReceiveMemoryWarning內(nèi)調(diào)用super的didReceiveMemoryWarning會(huì)將controller的view進(jìn)行釋放。所以我們不能將controller的view再次釋放。

處理方法:

-(void)didReceiveMemoryWarning{

? ? ? ? [super?didReceiveMemoryWarning];//如沒(méi)有顯示在window上,會(huì)自動(dòng)將self.view釋放。

? ? ? ? //?ios6.0以前,不用在此做處理,self.view釋放之后,會(huì)調(diào)用下面的viewDidUnload函數(shù),在viewDidUnload函數(shù)中做處理就可以了。

}

-(void)viewDidUnload{

? ? ? ? //?Release?any?retained?subviews?of?the?main?view.不包含self.view

? ? ? ? //處理一些內(nèi)存和資源問(wèn)題。?

? ? ? ? [super?viewDidUnload];

}

2、iOS6.0及以上版本的內(nèi)存警告:

調(diào)用didReceiveMemoryWarning內(nèi)調(diào)用super的didReceiveMemoryWarning

只是釋放controller的resouse,不會(huì)釋放view

處理方法:

-(void)didReceiveMemoryWarning{

? ? ? ? [super didReceiveMemoryWarning];//即使沒(méi)有顯示在window上,也不會(huì)自動(dòng)的將self.view釋放。

? ? ? ? // Add code to clean up any of yourown resources that are no longer necessary.

? ? ? ? //此處做兼容處理需要加上ios6.0的宏開(kāi)關(guān),保證是在6.0下使用的,6.0以前屏蔽以下代碼,否則會(huì)在下面使用self.view時(shí)自動(dòng)加載viewDidUnLoad

? ? ? ?if ([[UIDevicecurrentDevice].systemVersion floatValue] >= 6.0) {

? ? ? ? //需要注意的是self.isViewLoaded是必不可少的,其他方式訪問(wèn)視圖會(huì)導(dǎo)致它加載,在WWDC視頻也忽視這一點(diǎn)。

? ? ? ? ? ? ? if (self.isViewLoaded &&!self.view.window)//是否是正在使用的視圖{

? ? ? ? ? ? ? ? ? ? ? // Add code to preserve data storedin the views that might be

? ? ? ? ? ? ? ? ? ? ? // needed later.

? ? ? ? ? ? ? ? ? ? ? // Add code to clean up other strongreferences to the view in

? ? ? ? ? ? ? ? ? ? ? // the view hierarchy.

? ? ? ? ? ? ? ? ? ? ? self.view = nil;//目的是再次進(jìn)入時(shí)能夠重新加載調(diào)用viewDidLoad函數(shù)。

? ? ? ? ? ? ? ?}

? ? ? ? }

}

但是似乎這么寫(xiě)相對(duì)于以前并不省事。最終我們找到一篇文章,文章中說(shuō)其實(shí)并不值得回收這部分的內(nèi)存,原因如下:

1. UIView是UIResponder的子類,而UIResponder有一個(gè)CALayer的成員變量,CALayer是具體用于將自己畫(huà)到屏幕上的。

2. CALayer是一個(gè)bitmap圖象的包裝類,當(dāng)UIView調(diào)用自身的drawRect時(shí),CALayer才會(huì)創(chuàng)建這個(gè)bitmap圖象類。

3.具體占內(nèi)存的其實(shí)是一個(gè)bitmap圖象類,CALayer只占48bytes, UIView只占96bytes。而一個(gè)iPad的全屏UIView的bitmap類會(huì)占到12M的大小!

4.在iOS6時(shí),當(dāng)系統(tǒng)發(fā)出MemoryWarning時(shí),系統(tǒng)會(huì)自動(dòng)回收bitmap類。但是不回收UIView和CALayer類。這樣即回收了大部分內(nèi)存,又能在需要bitmap類時(shí),根據(jù)CALayer類重建。

所以,iOS6這么做的意思是:我們根本沒(méi)有必要為了幾十byte而費(fèi)力回收內(nèi)存。

生命周期圖

三、內(nèi)存泄漏分析解決方法

(一) 靜態(tài)分析

通過(guò)靜態(tài)分析我們可以最初步的了解到代碼的一些不規(guī)范的地方或者是存在的內(nèi)存泄漏,這是我們第一步對(duì)內(nèi)存泄漏的檢測(cè)。當(dāng)然有一些警告并不是我們關(guān)心的可以略過(guò)。

(二) 通過(guò)instruments來(lái)檢查內(nèi)存泄漏

這個(gè)方法能粗略的定位我們?cè)谀睦锇l(fā)生了內(nèi)存泄漏。方法是完成一個(gè)循環(huán)操作,如果內(nèi)存增長(zhǎng)為0就證明我們程序在該次循環(huán)操作中不存在內(nèi)存泄漏,如果內(nèi)存增長(zhǎng)不為0那證明有可能存在內(nèi)存泄漏,當(dāng)然具體問(wèn)題需要具體分析。

(三) 代碼測(cè)試內(nèi)存泄漏

在做這項(xiàng)工作之前我們要注意一下,在dealloc的方法中我們是否已經(jīng)釋放了該對(duì)象所擁有的所有對(duì)象。觀察對(duì)象的生成和銷毀是否配對(duì)。準(zhǔn)確的說(shuō)就是init(創(chuàng)建對(duì)象的方法)和dealloc是否會(huì)被成對(duì)觸發(fā)(簡(jiǎn)單說(shuō)來(lái)就是走一次創(chuàng)建對(duì)象就有走一次dealloc該對(duì)象)。

四、內(nèi)存檢查工具

編譯和分析工具Analyze

內(nèi)存泄漏檢測(cè)工具—Leak

內(nèi)存猛增檢測(cè)工具—Allocations

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,217評(píng)論 30 472
  • 轉(zhuǎn):http://www.cocoachina.com/programmer/20151019/13746.htm...
    Style_偉閱讀 1,343評(píng)論 0 3
  • 注:此文章來(lái)源:Job_Yang 的簡(jiǎn)書(shū) 1. Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么?Categ...
    廣益散人閱讀 1,360評(píng)論 0 13
  • 1.OC里用到集合類是什么? 基本類型為:NSArray,NSSet以及NSDictionary 可變類型為:NS...
    輕皺眉頭淺憂思閱讀 1,395評(píng)論 0 3
  • 我們看過(guò)了太多的感動(dòng)自己的故事,無(wú)論是一個(gè)動(dòng)作,無(wú)論是一絲問(wèn)候,亦或是一句溫柔的話,當(dāng)輕輕的碰到我們的心靈的一瞬間...
    楊雨樹(shù)閱讀 193評(píng)論 0 0