ios oc基礎(chǔ)加強(qiáng)視頻-源碼第01天01-內(nèi)存管理_第1頁
ios oc基礎(chǔ)加強(qiáng)視頻-源碼第01天01-內(nèi)存管理_第2頁
ios oc基礎(chǔ)加強(qiáng)視頻-源碼第01天01-內(nèi)存管理_第3頁
ios oc基礎(chǔ)加強(qiáng)視頻-源碼第01天01-內(nèi)存管理_第4頁
ios oc基礎(chǔ)加強(qiáng)視頻-源碼第01天01-內(nèi)存管理_第5頁
已閱讀5頁,還剩41頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

內(nèi)存管理傳智如意大師內(nèi)存移動設(shè)備的內(nèi)存極其有限,每個app所能占用的內(nèi)存是有限制的

下列行為都會增加一個app的內(nèi)存占用創(chuàng)建一個OC對象定義一個變量調(diào)用一個函數(shù)或者方法當(dāng)app所占用的內(nèi)存較多時,系統(tǒng)會發(fā)出內(nèi)存警告,這時得回收一些不需要再使用的內(nèi)存空間。比如回收一些不需要使用的對象、變量等如果app占用內(nèi)存過大系統(tǒng)可能會強(qiáng)制關(guān)閉app,造成閃退現(xiàn)象,影響用戶體驗內(nèi)存管理如何回收那些不需要再使用的對象?那就得學(xué)會OC的內(nèi)存管理所謂內(nèi)存管理,就是對內(nèi)存進(jìn)行管理,涉及的操作有:分配內(nèi)存:比如創(chuàng)建一個對象,會增加內(nèi)存占用清除內(nèi)存:比如銷毀一個對象,能減小內(nèi)存占用內(nèi)存管理的管理范圍任何繼承了NSObject的對象

(所有的OC對象,對象類型)對其他非對象類型(基本數(shù)據(jù)類型)無效(int、char、float、double、struct、enum等)只有OC對象才需要進(jìn)行內(nèi)存管理的本質(zhì)原因OC對象存放于堆里面非OC對象一般放在棧里面(棧內(nèi)存會被系統(tǒng)自動回收)將下面的代碼畫內(nèi)存圖分析,說明堆、棧存儲intmain(intargc,constchar*argv[]){inta=10;//棧

intb=20;//棧

Car*c=[[Caralloc]init];

//堆return0;}畫圖分析內(nèi)存分配過程voidm1(intn,intm){intsum=n+m;Car*c=[[Caralloc]init];}intmain(){

//分析m1方法被調(diào)用的時候內(nèi)存分配情況

m1(10,20);}舉例NSString*s1=@”bob”;NSString*s2=@”嘉木樣·洛桑久美·圖丹卻吉尼瑪”;**說明:同樣都是NSString*類型,但是占用的內(nèi)存字節(jié)數(shù)確不相同。**說明:整型變量,無論保存0還是10000都是占用4個字節(jié)。要說明的問題1.為什么基本數(shù)據(jù)類型可以放在“棧”中存儲?“對象類型”卻要放在堆中存儲?基本數(shù)據(jù)類型:大小固定對象數(shù)據(jù)類型:大小不固定2.為什么內(nèi)存管理只管理“對象類型”?代碼執(zhí)行完畢后,“堆內(nèi)存”不會自動銷毀,而“棧”內(nèi)存會自動彈棧(釋放)。內(nèi)存棧內(nèi)存(非OC對象)堆內(nèi)存(OC對象)a

=

10b

=

20地址:0xffc0Car對象計數(shù)器==1c

=

0xffc0堆和棧什么是引用計數(shù)器(ReferenceCounting)系統(tǒng)是如何判斷

什么時候需要回收一個對象所占用的內(nèi)存?根據(jù)對象的引用計數(shù)器什么是引用計數(shù)器每個OC對象都有自己的引用計數(shù)器它是一個整數(shù)(int類型)從字面上,可以理解為”對象被引用的次數(shù)”也可以理解為:它表示有多少人正在用這個對象OC對象4字節(jié)–引用計數(shù)器每個OC對象內(nèi)部都有4個字節(jié)的存儲空間來存放引用計數(shù)器引用計數(shù)器的作用簡單來說,可以理解為:引用計數(shù)器表示有多少人正在使用這個對象當(dāng)沒有任何人使用這個對象時,系統(tǒng)才會回收這個對象,也就是說當(dāng)對象的引用計數(shù)器為0時,對象占用的內(nèi)存就會被系統(tǒng)回收如果對象的計數(shù)器不為0,那么在整個程序運行過程,它占用的內(nèi)存就不可能被回收(除非整個程序已經(jīng)退出)任何一個對象,剛生下來的時候,引用計數(shù)器都為1。(對象一旦創(chuàng)建好,默認(rèn)引用計數(shù)器就是1)當(dāng)使用alloc、new或者copy創(chuàng)建一個對象時,對象的引用計數(shù)器默認(rèn)就是1引用計數(shù)器的操作要想管理對象占用的內(nèi)存,就得學(xué)會操作對象的引用計數(shù)器引用計數(shù)器的常見操作給對象發(fā)送一條retain消息,

可以使引用計數(shù)器值+1(retain方法返回對象本身)給對象發(fā)送一條release消息,

可以使引用計數(shù)器值-1給對象發(fā)送retainCount消息,可以獲得當(dāng)前的引用計數(shù)器值(通過%ld輸出查看)需要注意的是:release并不代表銷毀\回收對象,僅僅是計數(shù)器-1注意:我們只能通過操作對象計數(shù)器,間接控制對象的釋放與否。關(guān)閉ARC選中項目->選中All

->搜索Automatic

Reference

Counting修改為No演示retain、release、retainCount使用1.寫代碼演示2.畫圖說明。3.如何證明對象被銷毀了?重寫dealloc方法。dealloc當(dāng)一個對象的引用計數(shù)器值為0時這個對象即將被銷毀,其占用的內(nèi)存被系統(tǒng)回收系統(tǒng)會自動給對象發(fā)送一條dealloc消息(因此,從dealloc方法有沒有被調(diào)用,就可以判斷出對象是否被銷毀)dealloc方法的重寫一般會重寫dealloc方法,在這里釋放相關(guān)資源,

dealloc就是對象的遺言一旦重寫了dealloc方法,就必須調(diào)用[super

dealloc],并且放在最后面調(diào)用使用注意不能直接調(diào)用dealloc方法一旦對象被回收了,

它占用的內(nèi)存就不再可用,

堅持使用會導(dǎo)致程序崩潰(野指針錯誤)為了防止調(diào)用出錯,可以將“野指針”指向nil(0)。

野指針\空指針\僵尸對象僵尸對象已經(jīng)被銷毀的對象(不能再使用的對象)野指針指向僵尸對象(不可用內(nèi)存)的指針給野指針發(fā)消息會報EXC_BAD_ACCESS/EXC_BREAKPOINT錯誤(messagesenttodeallocatedinstance0x100100350)空指針沒有指向存儲空間的指針(里面存的是nil,也就是0)給空指針發(fā)消息是沒有任何反應(yīng)的,不會提示出錯!為了避免野指針錯誤的常見辦法在對象被銷毀之后,將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔?p=nil)輸出“野指針”與“指向僵尸對象的指針”地址通過NSLog(@”-----%p-----“,p1);輸出對象的地址來查看,僵尸對象與nil對象的區(qū)別。nil對象表示不指向任何對象僵尸對象,表示指向了一個已經(jīng)被釋放的對象。關(guān)閉ARC功能(iOS5開始)要想手動調(diào)用retain、release等方法,就必須關(guān)閉ARC功能開啟僵尸對象監(jiān)控默認(rèn)情況下,Xcode是不會管僵尸對象的,使用一塊被釋放的內(nèi)存也不會報錯。為了方便調(diào)試,應(yīng)該開啟僵尸對象監(jiān)控多對象內(nèi)存管理單個對象的內(nèi)存管理,看起來非常簡單如果對多個對象進(jìn)行內(nèi)存管理,并且對象之間是有聯(lián)系的,那么管理就會變得比較復(fù)雜1.多個變量同時使用(指向)同一個對象2.多個對象之間互相有關(guān)聯(lián)關(guān)系。其實,多個對象的管理思路跟很多游戲的房間管理差不多比如斗地主\

QQ堂總的來說,有這么幾點管理規(guī)律只要還有人在用某個對象,那么這個對象就不會被回收只要你想用這個對象,就讓對象的計數(shù)器+1當(dāng)你不再使用這個對象時,就讓對象的計數(shù)器-1示例代碼:每次有新變量引用對象都要retain。用完都要releasePerson*p1=[[Personalloc]init];

[p1retain];Person*p2=p1;

[p1retain];Person*p3=p1;

//使用對象[p3release];[p2release];[p1release];問題1:這段代碼是否有內(nèi)存問題?通過dealloc驗證問題2:如果把第一行與最后一行之間的所有retain、release都刪除掉,那么行嗎?(在p1

release后,p2、p3還需要使用的)**注意:手動內(nèi)存管理的時候,每次賦值對象的時候需要手動retain,不用的時候需要手動release。Person擁有Car對象案例:結(jié)合畫圖演示!步驟:1.創(chuàng)建Person類、Car類,并重寫每個類的dealloc方法。2.在Person類中,增加一個Car類型的屬性。自己寫get、set方法。3.在main函數(shù)中,創(chuàng)建Person、Car對象,然后將Car對象賦值給Person對象。最后Person對象release一次,Car對象release一次。提問:有沒有內(nèi)存問題?這樣寫合理嗎?4.因為上面的代碼沒有進(jìn)行內(nèi)存管理,所以car只要release一次,所有其他地方都不能用了,這樣做不合理。5.setCar方法中:增加一個retain重寫dealloc方法:對car執(zhí)行一次release換車了:重新賦值一個新car的時候,對舊car執(zhí)行一次release重復(fù)換同樣的車:判斷如果不是同一個對象,然后再執(zhí)行set賦值。演示重復(fù)賦值同一個對象Person擁有Car對象案例演示點:正常創(chuàng)建一個Person對象、Car對象進(jìn)行內(nèi)存管理讓Person對象擁有Car對象進(jìn)行內(nèi)存管理關(guān)鍵點:如果在為屬性賦值的時候不進(jìn)行內(nèi)存管理,那么在p對象釋放前Car對象已經(jīng)釋放了。畫圖演示。set方法的內(nèi)存管理set方法-(void)setCar:(Car*)car{

if(car!=_car){

//對當(dāng)前正在使用的車(舊車)做一次release[_car

release];

//對新車做一次retain操作

_car=[carretain];}}dealloc方法的內(nèi)存管理dealloc方法-(void)dealloc{

//當(dāng)人不在了,代表不用車了

//對車做一次release操作[_car

release];

//

self.car

=

nil;[super

dealloc];}介紹:self.car=nil;這種寫法。錯誤寫法,學(xué)了autorelease后回來再看。下面代碼都會引發(fā)內(nèi)存泄露p.dog=[[Dog

alloc]init];[[Dog

alloc]init].weight=20.8;內(nèi)存管理原則蘋果官方規(guī)定的內(nèi)存管理原則誰創(chuàng)建誰release

:

如果你通過alloc、new或copy、mutableCopy來創(chuàng)建一個對象,那么你必須調(diào)用release或autorelease誰retain誰release

:只要你調(diào)用了retain,就必須調(diào)用一次release總結(jié)一下就是有加就有減

曾經(jīng)讓對象的計數(shù)器+1,就必須在最后讓對象計數(shù)器-1在自己負(fù)責(zé)的區(qū)域內(nèi)(某個方法范圍內(nèi)、某個對象內(nèi)等。):有+,就得有-。@property編寫一個Person類、Car類、Dog類,并重寫每一個類的dealloc方法。讓Person類擁有car屬性、dog屬性,自己編寫car屬性與dog屬性的get、set方法(復(fù)習(xí)內(nèi)存管理代碼)通過@property關(guān)鍵字自動生成內(nèi)存管理代碼@property參數(shù)控制set方法的內(nèi)存管理retain

:release舊值,retain新值(用于OC對象),要配合nonatomic使用。assign

:直接賦值,不做任何內(nèi)存管理(默認(rèn),用于非OC對象類型)copy

:release舊值,copy新值(一般用于NSString*)控制需不需生成set方法readwrite

:同時生成set方法和get方法(默認(rèn))readonly

:只會生成get方法多線程管理atomic

:性能低(默認(rèn))nonatomic

:性能高(為iOS系統(tǒng)開發(fā)軟件建議使用,為mac開發(fā)軟件可以使用atomic)@property參數(shù)控制set方法和get方法的名稱setter

:設(shè)置set方法的名稱,一定有個冒號:getter

:設(shè)置get方法的名稱@property(nonatomic,retain,setter=setUserName:,getter=getUserName)NSString*name;一般只有BOOL類型的屬性的get方法才會使用getter修改一下方法名為isXxxx,其他很少用的。@property(nonatomic,assign)BOOLrich;@property(nonatomic,assign,getter=isRich)BOOLrich;使用@property案例課上案例:電商app類分析作業(yè):微博案例,使用@property生成內(nèi)存管理代碼。首先禁用ARC。@class遇到的問題:1.要在某個類的頭文件中使用另外一個類型,必須通過#import來引入另外一個類型的頭文件,這樣一旦被引用的頭文件被修改,所有引用該頭文件的文件都得修改重新編譯,造成低效率3.循環(huán)引用(循環(huán)依賴)問題作用可以簡單地引用一個類簡單使用@class

Dog;僅僅是告訴編譯器:

Dog是一個類;并不會包含Dog這個類的所有內(nèi)容具體使用在.h文件中使用@class引用一個類在.m文件中使用#import包含這個類的.h文件注意:繼承某個類的時候不能使用@class,必須#import@class和#import作用上的區(qū)別#import會包含引用類的所有信息(內(nèi)容),包括引用類的變量和方法@class僅僅是告訴編譯器有這么一個類,

具體這個類里有什么信息,完全不知效率上的區(qū)別如果有上百個頭文件都#import了同一個文件,或者這些文件又依次被#import,那么一旦最開始的頭文件稍有改動,后面引用到這個文件的所有類都需要重新編譯一遍,編譯效率非常低相對來講,使用@class方式就不會出現(xiàn)這種問題了

@class其他使用場景對于循環(huán)依賴關(guān)系來說,比方A類引用B類,同時B類也引用A類這種嵌套包含的代碼編譯會報錯

當(dāng)使用@class在兩個類相互聲明,就不會出現(xiàn)編譯報錯#import"B.h"@interfaceA:NSObject{

B*_b;}@end#import“A.h"@interfaceB:NSObject{

A*_a;}@end@class

B;@interfaceA:NSObject{

B*_b;}@end@class

A;@interfaceB:NSObject{

A*_a;}@end循環(huán)retain(內(nèi)存管理的問題,無法釋放)循環(huán)retain的場景比如A對象retain了B對象,B對象retain了A對象循環(huán)retain的弊端這樣會導(dǎo)致A對象和B對象永遠(yuǎn)無法釋放循環(huán)retain的解決方案當(dāng)兩端互相引用時,應(yīng)該一端用retain、一端用assign,使用了assign后,dealloc中就不需要release了。案例演示1.創(chuàng)建Person類、Dog類,并重寫每個類型的dealloc方法2.在main函數(shù)中創(chuàng)建Person對象、Dog對象,查看對象釋放情況。3.讓Person對象擁有Dog(通過@property

+

retain實現(xiàn)),同時在dealloc中釋放dog,再查看main函數(shù)中的對象釋放情況。4.讓Dog對象擁有Person對象(通過@property

+

retain實現(xiàn)),同時在dealloc中釋放person,再查看main函數(shù)中的對象釋放情況。autorelease基本編程模型1.創(chuàng)建對象池2.把要自動release的對象放到對象池中3.當(dāng)對象池釋放的時候?qū)υ摮刈又械乃袑ο笞鲆淮蝦elease。autorelease簡介autorelease方法的基本作用給對象發(fā)送一條autorelease消息,會將對象放到一個自動釋放池中當(dāng)自動釋放池被銷毀時,會對池子里面的所有對象做一次release操作會返回對象本身調(diào)用完autorelease方法后,對象的計數(shù)器不變autorelease的好處不用再關(guān)心對象釋放的時間不用再關(guān)心什么時候調(diào)用releaseautorelease的使用注意占用內(nèi)存較大的對象不要隨便使用autorelease占用內(nèi)存較小的對象使用autorelease,沒有太大影響自動釋放池在iOS程序運行過程中,會創(chuàng)建無數(shù)個池子。這些池子都是以棧結(jié)構(gòu)存在(先進(jìn)后出)當(dāng)一個對象調(diào)用autorelease方法時,會將這個對象放到棧頂?shù)尼尫懦刈詣俞尫懦氐膭?chuàng)建方式

iOS5.0前

NSAutoreleasePool*pool=[[NSAutoreleasePool

alloc]init];

[poolrelease];//[pooldrain];

iOS5.0開始@autoreleasepool{}在開發(fā)iOS程序時會自動創(chuàng)建autoreleasepoolautorelease的常見錯誤alloc之后調(diào)用了autorelease,又調(diào)用release。野指針錯誤。Person*p=[[[Person

alloc]init]autorelease];[prelease];連續(xù)調(diào)用多次autorelease,則在“自動釋放池”銷毀的時候?qū)υ搶ο笞龆啻蝦elease??赡茉斐梢爸羔樺e誤。Person*p=[[[[Person

alloc]init]autorelease]autorelease];autorelease和release使用對比使用

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論