<span style="font-size:18px;">OC內存管理 1、基本原理 (一)爲何要進行內存管理。因爲移動設備的內存極其有限。因此每個APP所佔的內存也是有限制的,當app所佔用的內存較多時。系統就會發出內存警告,這時需要回收一些不需要再繼續使用的內存空間,比方回收一些再也不使用的對象和變量等。 管理範圍:不論什麼繼承NSObject的對象,對其它的基本數據類型無效。 本質緣由是因爲對象和其它數據類型在系統中的存儲空間不同,其它局部變量主要存放於棧中。而對象存儲於堆中。當代碼塊結束時這個代碼塊中涉及的所有局部變量會被回收,指向對象的指針也被回收。此時對象已經沒有指針指向。但依舊存在於內存中,形成內存泄露。 (二)對象的基本結構 每個OC對象都有本身的引用計數器。是一個整數表示對象被引用的次數。即現在有多少東西在使用這個對象。對象剛被建立時,默認計數器值爲1。當計數器的值變爲0時。則對象銷燬。 在每個OC對象內部,都專門有4個字節的存儲空間來存儲引用計數器。 (三)引用計數器的做用 推斷對象要不要回收的惟一根據就是計數器是否爲0,若不爲0則存在。 (四)操做 給對象發送消息,進行相應的計數器操做。 Retain消息:使計數器+1,改方法返回對象自己 Release消息:使計數器-1(並不表明釋放對象) retainCount消息:得到對象當前的引用計數器值 (五) 對象的銷燬 當一個對象的引用計數器爲0時。那麼它將被銷燬。其佔用的內存被系統回收。ios
當對象被銷燬時,系統會本身主動向對象發送一條dealloc消息,一般會重寫dealloc方法。在這裏釋放相關的資源,dealloc就像是對象的「臨終遺言」。一旦重寫了dealloc方法就必須調用[super dealloc],而且放在代碼塊的最後調用(不能直接調用dealloc方法)。 一旦對象被回收了。那麼他所佔領的存儲空間就再也不可用,堅持使用會致使程序崩潰(野指針錯誤)。 2、相關概念和使用注意 野指針錯誤:訪問了一塊壞的內存(已經被回收的。不可用的內存)。 殭屍對象:所佔內存已經被回收的對象,殭屍對象不能再被使用。(打開殭屍對象檢測) 空指針:沒有指向不論什麼東西的指針(存儲的東西是0,null,nil),給空指針發送消息不會報錯 注意:不能使用[p retaion]讓殭屍對象起死復生。 3、內存管理原則 (一)原則 僅僅要還有人在使用某個對象,那麼這個對象就不會被回收。 僅僅要你想使用這個對象,那麼就應該讓這個對象的引用計數器+1; 當你不想使用這個對象時,應該讓對象的引用計數器-1; (二)誰建立,誰release (1)假設你經過alloc,new,copy來建立了一個對象,那麼你就必須調用release或者autorelease方法 (2)不是你建立的就不用你去負責 (三)誰retain。誰release 僅僅要你調用了retain。無論這個對象時怎樣生成的,你都要調用release (四)總結 善始善終,有加就應該有減。多線程
曾經讓某個對象計數器加1,就應該讓其在最後-1. 4、內存管理代碼規範 (一)僅僅要調用了alloc,就必須有release(autorelease) (二)Set方法的代碼規範 (1)基本數據類型:直接複製 -(void)setAge:(int)age { _age=age; } (2)OC對象類型 -(void)setCar:(Car *)car { //1.先推斷是否是新傳進來的對象 If(car!=_car) { //2 對舊對象作一次release [_car release];//若沒有舊對象,則沒有影響 //3.對新對象作一次retain _car=[car retain]; } } (三)dealloc方法的代碼規範 (1)必定要[super dealloc],而且要放到最後 (2)對self(當前)所擁有的的其它對象作一次release操做 -(void)dealloc { [_car release]; [super dealloc]; } 5、@property的參數 (1)內存管理相關參數 Retain:對對象release舊值。retain新值(適用於OC對象類型) Assign:直接賦值(默認。適用於非oc對象類型) Copy:release舊值,copy新值 (2)是否要生成set方法(若爲僅僅讀屬性。則不生成) Readonly:僅僅讀。僅僅會生成getter的聲明和實現 Readwrite:默認的。同一時候生成setter和getter的聲明和實現 (3)多線程管理(蘋果在必定程度上屏蔽了多線程操做) Nonatomic:高性能。通常使用這個 Atomic:低性能 (4)Set和get方法的名稱 改動set和get方法的名稱,主要用於布爾類型。因爲返回布爾類型的方法名通常以is開頭,改動名稱通常用在布爾類型中的getter。 @propery(setter=setAbc,getter=isRich) BOOL rich; BOOL b=p.isRich;// 調用 6、內存管理中的循環引用問題以及解決 案例:每個人有一張身份證,每張身份證相應一我的。不能使用#import的方式相互包括,這就造成了循環引用。 新的keyword:@class 類名;——解決循環引用問題。提升性能 @class僅僅告訴編譯器,在進行編譯的時候把後面的名字做爲一個類來處理。app
(1)@class的做用:聲明一個類,告訴編譯器某個名稱是一個類 (2)開發中引用一個類的規範 1)在.h文件裏使用@class來聲明類 2)在.m文件裏真正要使用到的時候,使用#import來包括類中的所有東西 (3)兩端循環引用的解決方法 一端使用retain,一端使用assign(使用assign的在dealloc中也不用再release) 7、Autorelease (一)基本使用方法 (1)會將對象放到一個本身主動釋放池中 (2)當本身主動釋放池被銷燬時,會對池子裏的所有對象作一次release (3)會返回對象自己 (4)調用完autorelease方法後,對象的計數器不受影響(銷燬時影響) (二)優勢 (1)不需要再關心對象釋放的時間 (2)不需要再關心何時調用release (三)使用注意 (1)佔用內存較大的對象。不要隨便使用autorelease,應該使用release來精確控制 (2)佔用內存較小的對象使用autorelease,沒有太大的影響 (四)錯誤寫法 (1)連續調用屢次autorelease。釋放池銷燬時執行兩次release(-1嗎?) (2)Alloc以後調用了autorelease,以後又調用了release。 (五)本身主動釋放池 (1)在ios程序執行過程當中,會建立無數個池子,這些池子都是以棧結構(先進後出)存在的。 (2)當一個對象調用autorelease時,會將這個對象放到位於棧頂的釋放池中 (六)本身主動釋放池的建立方式 (1)ios 5.0曾經的建立方式 NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; ````````````````` [pool release];//[pool drain];用於mac (2)Ios5.0之後 @autoreleasepool {//開始表明建立本身主動釋放池 ······· }//結束表明銷燬本身主動釋放池 (七)Autorelease注意 (1)系統自帶的方法中。假設不包括alloc new copy等。則這些方法返回的對象都是autorelease的。如[NSDate date]; (2)開發中經常會寫一些類方法來高速建立一個autorelease對象,建立對象時不要直接使用類名。而是使用self 8、ARC內存管理機制 (一)ARC的推斷準則: 僅僅要沒有強指針指向對象。對象就會被釋放。post
(二)指針分類: (1)強指針:默認的狀況下,所有的指針都是強指針,keywordstrong (2)弱指針:_ _weakkeyword修飾的指針 聲明一個弱指針例如如下: _ _weak Person *p; ARC中。僅僅要弱指針指向的對象不在了。就直接把弱指針作清空操做。 _ _weak Person *p=[[Person alloc] init];//不合理。對象一建立出來就被釋放掉。對象釋放掉後,ARC把指針本身主動清零。性能
ARC中在property處再也不使用retain,而是使用strong,在dealloc中不需要再[super dealloc]。atom
@property(nonatomic,strong)Dog *dog;// 意味着生成的成員變量_dog是一個強指針,至關於曾經的retain。spa
假設換成是弱指針,則換成weak,不需要加_ _。 (三)ARC的特色總結: (1)不一樣意調用release,retain,retainCount (2)不一樣意重寫dealloc,但是不一樣意調用[super dealloc] (3)@property的參數: Strong:至關於原來的retain(適用於OC對象類型),成員變量是強指針 Weak:至關於原來的assign,(適用於oc對象類型),成員變量是弱指針 Assign:適用於非OC對象類型(基礎類型) (四)補充 讓程序兼容ARC和非ARC部分。轉變爲非ARC -fno-objc-arc 轉變爲ARC的。 -f-objc-arc 。 ARC也需要考慮循環引用問題:一端使用retain,還有一端使用assign。線程
提示:字符串是特殊的對象,但不需要使用release手動釋放,這樣的字符串對象默認就是autorelease的,不用額外的去管內存。</span>指針