1. 程式人生 > >黑馬程式設計師-OC記憶體管理

黑馬程式設計師-OC記憶體管理

(一)手動管理記憶體

棧:存放區域性變數(所佔用記憶體會自動銷燬) -> 指向堆空間

堆:存放物件(所佔用記憶體需手動銷燬)

管理範圍:所有繼承NSObject的類物件

1.記憶體洩露?記憶體洩露的後果?

_age = [age ratain];

自己申請的記憶體,沒有釋放 會使記憶體中存在很多的垃圾,浪費不必要的記憶體

2.應用計數器:用於計算物件被使用的次數,是一個整數(每個物件都有自己的引用計數器:佔4個位元組) 

(1)當使用alloc、new或copy建立新物件時,新物件的引用計數器被設定為1.

(2)當引用計數器為0時,則此物件所佔用記憶體就會被回收。(傳送release訊息時,計數器減1)

(3)給物件傳送retainCount訊息獲取當前的計數器值

   注:retain方法返回的是物件本身(有返回值)

3.物件的銷燬
(1)引用計數器為0,物件佔用的記憶體被系統收回。(物件變成殭屍物件。指向此方法的指標值變為0)
(2)當物件被銷燬時,系統會自動向物件傳送dealloc訊息。(物件遺言)
(3)一般要重寫dealloc方法。(必須呼叫super的dealloc)

eg:

- (void)dealloc
{
       [super dealloc];
}
4.概念
(1)野指標:指向殭屍物件(不可用記憶體)的指標。
注:給野指標傳送訊息會報錯,報錯提示:EXC_BAD_ACCESS

(2)殭屍物件:所佔用記憶體已經被回收的物件,殭屍物件不能再使用、
(3)空指標:沒有指向任何東西的指標(儲存的東西是nil、NULL、0)
注:給空指標傳送訊息不會報錯


5.記憶體管理原則:
(1)當想使用(佔用)某個物件時,就應該讓物件的計數器+1 (讓物件做一個ratain操作)
eg:

_age = [age ratain];

(2)當不想使用(佔用)某個物件時,就應該讓物件的計數器-1 (讓物件做一次release操作) 

eg:

-(void)dealloc
{ 
        [_dog release];//物件計數器-1
        [super dealloc];
}


(3)誰retain,誰release;誰alloc,誰release。
注:物件在set方法中賦值時,應該進行一次retain操作。(基本資料型別不需要管理記憶體 )

6.set方法記憶體管理
(1)只要呼叫了alloc,則必須要有release(或autorelease);
如果物件不是通過alloc產生,則不需要release。

(2)set方法程式碼規範
1)基本資料型別:直接賦值(基本資料型別不需要進行記憶體管理)

eg:

- (void)setAge:(int)age
{
   _age = age; 
}

2)OC物件型別

eg:

- (void)setCar:(Car *)car
{
   if ( car != _car) // 1.先判斷是不是新傳進來的物件
   {
      [_car release]; // 2.對舊物件做一次release
      _car = [car retain]; //  3.對新物件做一次retain
   }                             
}

(3)dealloc程式碼規範
1>一定要有[super dealloc],而且要放到最後。
2>對self(當前)所擁有的其他物件做一次release

eg:

- (void)dealloc
{
    [_car release]; // 一旦Person release,則車也應該release
    [super dealloc]; // 這段一定要放最後
}

[email protected] 記憶體管理
@property (引數) 物件
eg :
@property (nonatomic,retain) Car *car;

(1)set方法記憶體管理的相關引數
retain:生成的setter方法中會release舊值,retain新值。(適用於OC物件型別)
assin:直接賦值(預設,適用於非OC物件型別)
copy: release舊值,copy新值。

(2)是否要生成set方法
readwrite:可讀寫,同時生成setter和getter的宣告、實現(預設)
readonly:只讀,只會生成getter的宣告、實現。

(3)多執行緒管理(多個執行緒同時呼叫某個方法)
nonatomic:代表方法不要考慮執行緒安全性問題,告訴系統不在set方法中生成多執行緒程式碼。(高效能,禁止多執行緒,推薦使用)
atomic:代表給方法進行加鎖,保證執行緒安全(預設,低效能)
執行緒保護機制:防止方法在未寫入完成時,被其它執行緒呼叫,造成資料錯誤。


(4)setter和getter方法的名稱
setter:setter = 方法名,決定了set方法的名稱,方法名一定有冒號:
getter:決定了get方法的名稱。(一般用在BOOL型別)

8.迴圈retain和@class
1>(1)@class使用方法:
作用: @class Card 僅僅告訴編譯器,Card只是一個類
使用場合:用於.h宣告此類,但是不會引入此類的方法和成員變數。
注意點:僅僅宣告這個類,不會將此類的方法和成員變數匯入,如果需要,則應該在.m檔案中#import此類。

(2)引用一個類的規範
1>在.h標頭檔案中用@class來宣告類
2>在.m原始檔中用#import來包含類的所有東西


(3)@class優點
1>解決迴圈包含的問題。- >只在.m 原始檔中進行引用(可以迴圈宣告,A中宣告B,B中宣告A)
2>提高了效能。->如果被引入類的標頭檔案進行了修改,不需要全部進行重新編譯。


(4)@class 和 #import 區別
1> #import方式會包含被引用類的所有資訊,包括被引用類的變數和方法;(使用類所有資訊,包括成員變數和方法)

@class方式只是告訴編譯器在A.h檔案中 ,宣告某個類,不知道此類的所有具體資訊。(僅僅宣告有這個類)

2>如果有上百個標頭檔案都#import了同一個檔案,那麼一旦被匯入檔案的標頭檔案稍有改動,後面引用到這個 

檔案的所有類的標頭檔案都需要重新拷貝,效率較低。(A->B,B->C,C->D.....一旦A變動,則後面都需要重新編譯。程式只編譯.h檔案)
使用@class方式就不會出現這種問題了,只需在原始檔中修改類即可,提高了效率。
(解決了迴圈包含問題)
3>在.m實現檔案中,如果需要引用到被引用類的成員變數或方法時,還需要使用#import方式引入被引用類。

2> 兩端迴圈引用解決方法(迴圈retain)

一端用retain,一端用assign。、
eg: Car 端 : @property (nonatomic,retain) Person *person;
Person端:@propertor (nonatomic,assign) Car *car

9. autorelease
eg: Person *p = [[[Person alloc] init] autorelease]; //必須存在釋放池,才能寫autorelease
作用:1>autorelease會將物件放到一個自動釋放池中,當自動釋放池被銷燬時,會對池子裡所有物件做一次release。
2>返回物件本身,且不影響物件計數器。
注:池子被銷燬時,物件不一定會被銷燬,只是做一次release。釋放池內可巢狀釋放池

eg:

int main()
{
    @autoreleasepool
    { // { 代表開始建立釋放池

    } // } 代表銷燬釋放

}

優點:1>不用在關心物件釋放的時間.
2>不需要關心什麼使用呼叫release。
缺點:不能精確控制物件銷燬時間。
使用注意:1>佔用記憶體較大的物件不要隨便使用autorelease(不能精確控制物件銷燬時間)
2>佔用記憶體較小的物件使用,則不會有太大影響。
建議:儘量使用release,因為可以精確控制物件銷燬。
使用規範:1>系統自帶的方法中,如果不包含alloc、new、copy,那麼這些方法返回的物件都是已經autorelease的
2>開發中經常寫一些類方法快速建立一個autorelease的物件。(不使用類名,使用self)

eg:
+ (id)Person  
{  
    return [[[self alloc] init] autorelease];  
}  

(二)自動管理記憶體

自動回收記憶體機制。
優點:不需要人為新增記憶體管理程式碼,提高了程式設計效率與安全性。
1.概念:編譯器會自動在適當的地方插入適當的retain、release、autorelease語句。(屬於編譯器特性)

2.ARC的判斷標準:
只要沒有強指標指向物件,就會釋放物件。
eg: Person *p = [[Person alloc] init];
p = nil;
程式碼解析:預設情況下,p是強指標。當p等於空時,就沒有強指標指向Person物件,這時候編譯器會自動將Person物件銷燬。

(1)強指標:預設情況下,指標都是強指標(__strong)
(2)弱指標: __weak 修飾
eg: __weak Person *p2 = p ; (p2就是個弱指標)

3. ARC特點:
(1)不允許手工呼叫release、retain、autoretain。
(2)允許重寫dealloc,但是不允許呼叫[super dealloc];
(3)@property引數
strong:成員變數是強指標,相當於以前retain(使用OC物件)
weak:成員變數是弱指標,相當於以前assign(使用OC物件)
assign:基本資料型別,直接賦值。(使用非OC物件)
(4)以前的retain,全部改為strong,其餘不變
eg: @property (nonatomic,retain) Car *car;

改為:@property (nonatomic,strong) Car *car;

4.某.m檔案不需要ARC方法
不需要ARC: 新增-fno-objc-arc

          需要ARC:-f-objc-arc 5.解決迴圈引用問題
1>ARC

一端用strong,一端用weak
eg: 
Dog 端 : @property (nonatomic,strong) Person *person;
Person端:@propertor (nonatomic,weak) Dog *car

2>非ARC
一端用retain,一端用assign
eg: Dog 端 : @property (nonatomic,retain) Person *person;
Person端:@propertor (nonatomic,assign) Dog *car

6.總結
ARC最大的優點就是極大的提高了程式編寫效率,開發者不需要關心物件的銷燬時間,不需要擔心程式的記憶體洩漏問題

相關推薦

黑馬程式設計師OC記憶體管理

(一)手動管理記憶體 棧:存放區域性變數(所佔用記憶體會自動銷燬) -> 指向堆空間 堆:存放物件(所佔用記憶體需手動銷燬) 管理範圍:所有繼承NSObject的類物件 1.記憶體洩露?記憶

黑馬程式設計師_OC之記憶體管理

記憶體管理 ------ IOS培訓、android培訓、期待與您交流!------- 一、基本原理:    1、記憶體管理的定義       1>、移動移動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的       2>、當app所佔用的記憶體

黑馬程式設計師09 OC 記憶體管理

                           ------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- 1.管理範圍 任何繼承了NSObject的物件,對其他基本資料型別(int、char、float、double

黑馬程式設計師】棧記憶體與堆記憶體

java中記憶體分配策略及堆和棧的比較    1 記憶體分配策略    按照編譯原理的觀點,程式執行時的記憶體分配有三種策略,分別是靜態的,棧式的,和堆式的.    靜態儲存分配是指在編譯時就能確定每個資料目標在執行時刻的儲存空間需求,因而在編譯時就可以給他們分配固定的記憶體空間.這種分配策略要求程式程式碼中

黑馬程式設計師_7k交通燈管理系統

package com.isoftstone.interview.traffic; /* * 每個Lamp元素代表一個方向上的燈,總共有12個方向,所有總共有12個Lamp元素。 * 有如下一些方向上的燈,每兩個形成一組,一組燈同時變綠或變紅,所以, * 程式程式碼只需要控制每組燈中的一個

黑馬程式設計師——面試——交通燈管理系統

                             ---------- android培訓、java培訓、java學習型技術部落格、期待與您交流! ----------   交通燈管理系統的專案需求 模擬實現十字路口的交通燈管理系統邏輯,具體需求如下: 非同步

黑馬程式設計師————OC記憶體管理_筆記整理(二)

一、@Prpperty引數 // 加上retain:表示生成的set方法,release舊值,retain新值 @property (retain) Book *book; // oc物件型別 //@property (nonatomic,retain) 類名 *屬性名

黑馬程式設計師 OC基礎: 記憶體管理

記憶體管理 簡述 每個 oc 物件都有自己的引用計數器,是一個整數,表示”物件被引用的次數”.佔四位元組 計數器預設值為1 當為0時,物件佔用的記憶體會被系統回收. 引用的操作 給物件傳送一條 retain 計數器+1 給物件傳送一

黑馬程式設計師-OC學習筆記-----記憶體管理

移動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的.當app所佔用的記憶體較多時,系統會發出記憶體警告,這時得回收一些不需要再使用的記憶體空間。比如回收一些不需要使用的物件、變數等。基本的資料型別是放在記憶體的棧裡面,這是不需要我們去管理的,系統會自動回收。但是

黑馬程式設計師——OC記憶體管理

1.記憶體的建立和釋放 讓我們以Object-c世界中最最簡單的申請記憶體方式展開,談談關於一個物件的生命週期。首先建立一個物件: id testObject = [[ClassName alloc] init]; //“ClassName”是任何你

黑馬程式設計師——OC筆記之記憶體管理

Objective-C提供了三種記憶體管理方式: MannulReference Counting(MRC,手動管理, iOS4.1之前的版本) automatic reference counting(ARC,自動引用計數,iOS4.1 之後推出的) garbage collection(垃圾回收)。iO

[黑馬程式設計師][OC]記憶體管理

一、記憶體管理的基本原理 1.什麼是記憶體管理 移動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的,當app所佔用的記憶體較多時,系統會發出記憶體警告,這時得回收 一些不需要再使用的記憶體空間。比如回收一些不需要使用的物件、變數等。管理範圍:任何繼承了NS

黑馬程式設計師————OC記憶體管理_ARC

ARC( Autom Reference Counting) 是一個編譯器特性,會自動檢測幫我們release 一、ARC基本原理 1.編譯器特性 編譯程式碼的過程中會自動檢測哪裡需要插入自動釋放記憶體的程式碼 // 新建立一個物件,會自動釋放物件 P

黑馬程式設計師OC語言基礎—記憶體管理

之前我們已經提到過C語言中的記憶體儲存空間。有五大區域:堆、棧、自由儲存區、全域性\靜態儲存區和常量儲存區。 OC是以C語言為基礎的,所以也分這五大區域。 下面我們討論一下OC中記憶體管理的規律。 一、引用計數器 1.每個OC物件都有自己的引用計數器,是一個整數,即物件被

黑馬程式設計師-----OC記憶體管理原則

------<a href="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! ------- Objective-C對記憶體管理的方法

黑馬程式設計師——IOS基礎——OC記憶體管理

=====================引用計數器開始==================== 基本型別資料存放在棧中,物件存放在堆中 棧中的資料系統自動回收 堆空間中的資料動態分配,不能自動分配,容易引起記憶體洩露 需要給物件傳送訊息,讓它回收,即呼叫物件的回收方法

黑馬程式設計師----oc加強筆記----記憶體管理

                              引用計數器: 每個OC物件都有自己的引用計數器,是一個整數表示物件被引用的次數,即現在有多少東西在使用這個物件。物件剛被建立時,預設計數器值為1,當計數器的值變為0時,則物件銷燬。                 2)對引用計數器的操作     

黑馬程式設計師——OC基礎—記憶體管理

=== 記憶體管理機制 === OC的區域性變數在程式碼塊結束時被系統銷燬, 記憶體被回收. OC的物件, 內部有引用計數器, 當引用計數器的值為0時, 被系統銷燬, 記憶體被回收. 區域性變數存放在棧中. 物件存放在堆中. 注意, 物件指標還是存放在棧中, 物件本身佔用的記憶體存放在堆中. 在OC

黑馬程式設計師——OC基礎---記憶體管理

1. 控制set方法的記憶體管理 retain : release舊值,retain新值(用於OC物件)  assign : 直接賦值,不做任何記憶體管理(預設,用於非OC物件型別) copy   : release舊值,copy新值(一般用於NSString *) 2.  控制需不需生成set方法 re

黑馬程式設計師-----OC記憶體管理(二)

---------------------- ASP.Net+Unity開發、.Net培訓、期待與您交流! ---------------------- OC記憶體管理1>記憶體管理原則 ①只要還有人在用某個物件,那麼這個物件就不會被回收;只要想用這個物件,就讓計數