国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

黑馬程序員--Objective-C內存管理我之見解

2019-11-14 18:32:40
字體:
來源:轉載
供稿:網友

------<a target="blank">java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! -------

內存管理

為什么要進行內存管理?
因為設備的內存空間是有限的,如果一直占用,而不回收空間,內存就會被一直占用,導致內存不足,  系統就會就會報警,嚴重的可能直接退出程序,因此,在軟件開發過程中,需要進行內存管理,以保證高效快速的分配內存,并且在適當的時候釋放和回收內存資源。
 
內存管理的范圍?
任何繼承了NSObject的對象,對基本數據
類型無效,主要對堆區的內存進行管理。
 
為什么要對堆區的內存空間進行管理,基本數據類型不需要管理呢?
因為基本數據類型的數據會被放入棧中,他們依次緊密排列,遵循先進后出的原則,系統會自動進行管理。 而對象類型會被放到堆中,堆中的內存是不連續的,無法自動釋放,所以需要我們管理。
 
內存管理的原理?
(1)對象的所有權及引用計數器
      對象的所有權:任何對象都有一個或多個擁有者,只要一個對象至少還有一個擁有者,他就不會被釋放
(2) 任何自己創建的對象都歸自己所有,可以使用alloc和new開頭或名字中包含copy的方法創建對象,使用return來獲得一個對象的所有權。
(3) OC中都有專門8個字節的存儲空間來存儲引用計數器,用整數表示對象被引用的次數。
引用計數器是判斷對象是否回收內存空間的依據。
(4) 給對象發送消息
         return  計數器+1,方法返回對象本身
         release  計數器-1,但不代表釋放,autorelease 也可使引用計數器-1.
         retaincount消息  用來獲得當前引用計數器的值 
 
引用計數器為0,系統像對象發送dealloc消息,(調用[super dealloc]方法,一定要寫在后面)釋放相關資源,對象被回收后將不能在被使用(僵尸對象),僵尸對象不可復活,否則會導致程序崩潰,導致野指針錯誤
 
如何防止野指針錯誤,在對象被釋放后賦值為nil.
 
內存管理的分類?
MRC 手動內存管理
ARC 自動內存管理
垃圾回收   iOS不支持
 
內存管理的原則?
如果還有人使用某個對象,這個對象就不會被回收。
如果有人想使用這個對象 那么就應給讓對象的引用計數器+1
如果不想使用這個對象,就有那個該讓對象的引用計數器-1
誰創建誰relesase   誰retain 誰release.有始有終 有加有減。
 
內存研究的內容?
野指針 內存泄露
野指針 定義的指針變量沒有初始化。指向的空間已經被釋放
內存泄露 :如果棧區的的空間已經被釋放了,而堆區的空間還沒與被釋放,堆區的空間就被泄露了。 

 

 

 單個對象內存管理

  1. 野指針錯誤:

      訪問了一塊壞的內存

  2. 僵尸對象:

      如果一個對象已經被釋放,這個對象被稱為僵尸對象

  3. 空指針:

      沒有指向任何東西的指針,給空指針發送消息不會報錯

  4. nil和NULL的區別

     nil  對象指針

     NULL 類對象指針

   5. 避免使用僵尸對象的方法:

      對象釋放了以后,給對象賦值為nil

   6. 單個對象的內存泄露

      情況1: 創建完成,使用之后,沒有release

 

情況2: 沒有遵守內存管理原則

 

        Dog *d = [[Dog alloc] init]

 [d retain];

 

      情況3: 不當的使用了nil

 

Dog *d = [[Dog alloc] init]

 

   d = nil;

 

      情況4:  在方法中對傳入的對象進行了retain

 

Dog *d = [[Dog alloc] init]

 

[d compareColorWithOther: d];

 

 

基本數據類型set方法的寫法    直接賦值

  

     -(void)setSpeed:(int)speed{ _speed = speed;}

 

 

對于對象作為另外一個類的實例變量

  

  -(void)setDog:(Dog *)dog{if(_dog!=dog){   //先判斷是不是原來的對象[_dog release];  //不是原來的對象做一次release,_dog = [dog retain];}}
 

@PRoperty 參數
格式:@property (參數1,參數2) 數據類型 方法名 

1.是否要生成set方法

readwrite : 同時生成setter和getter的聲明、實現

readonly :只會生成getter的聲明和實現

2.多線程管理

nonatomic :性能高(一般用這個)

atomic :性能低(默認)

3.set管理相關參數

retain :release舊值,return新值(適用于oc對象類型)

assign : 直接賦值(默認,適用于非OC對象)

copy : release舊值,copy新值
 
(1)  assign 直接賦值

  -(void)setCar:(Car *)car{

_car =car;

}

(2)  retain  release舊值,再retain新值

在一個類中有關聯其他對象的時候,這個對象的      @property(nonatomic,assign)  數據類型  方法名

     -(void)setCar:(Car *)car{if(_car!=car){   //先判斷是不是原來的對象[_car release];  //不是原來的對象做一次release,_car = [car retain];}}

 

 

(3) 是否要生成set方法(若只讀,則不生成)

readonly :只讀,只會生成getter的聲明和實現

readwrite:默認的,同時生成setter和getter的聲明和實現

(4)多線程管理

    @property(nonatomic,assign)  數據類型  方法名

   高性能,一般使用nonatomic

(5)  set和get方法的名稱

修改set和get方法的名稱,主要用于布爾類型。因為返回布爾類型的方法名一般以is開頭,修改名稱一般用 在布爾類型中的getter 

 

//替換set方法名稱  @property(nonatomic,assign ,setter= isVip:) //替換get方法名稱  @property(nonatomic,assign ,getter = isVip)//替換set,get方法名稱  @property(nonatomic,assign ,setter=isVip,getter = isVip:)  

 

 

 

 

循環retain問題

會導致兩個對象都會內存泄露

防止方法:

1) 讓某一個對象多釋放一次(注意順序) 

2) 推薦方法: 一端使用assign 一端使用retain

Dog.h#import <Foundation/Foundation.h>//#import "Person.h"@class Person;@interface Dog : NSObject//狗有個主人@property (nonatomic,retain) Person *owner;//這里用retain@endDog.m#import "Dog.h"#import "Person.h"@implementation Dog- (void)dealloc{    [_owner release];  //    NSLog(@"Dog dealloc");    [super dealloc];}@endPerson.h#import <Foundation/Foundation.h>//#import "Dog.h"@class Dog;@interface Person : NSObject//人擁有一條狗@property (nonatomic,assign) Dog *dog;//這里用assign@endPerson.m#import "Person.h"#import "Dog.h"@implementation Person- (void)dealloc{    //    [_dog release];  //nil這里不在需要    NSLog(@"Person dealloc");    [super dealloc];}@endmain.m    #import <Foundation/Foundation.h>#import "Dog.h"#import "Person.h"int main(int argc, const char * argv[]) {    @autoreleasepool {                Person *p = [Person new];  //1        Dog *d = [Dog new];   //1                //人有一條狗        p.dog = d;    //  d   1        d.owner = p;  //  p   2                [p release];  //0        [d release];  //        //        [d release];       //        [p release];            }    return 0;}                                                                                                                                                                                            

 

 

類方法不需要管理內存

autorelease基本使用

一個對象調用autorelease,將這個對象放到位于棧頂得的釋放池

@autoreleasepool

{  //   

}

概念介紹:  一種支持引用計數器的內存管理方式,可以暫時保存某個對象,然后再內存池自己的排干的時候對其中的每個對象發送release消息

好處:  不用擔心對象釋放時間,也不用擔心什么時候調用release

原理:

      autorelease實質上只是把對release的調用延遲了,對于每一個autorelease,該Object放入了當前的Autoreleasepool中,當該pool釋放時,該pool中的所有Object都會被調用release;

 

自動釋放池: 特殊的棧結構(數據結構),和內存的棧區結構不同

特點: 對象可以加入到自動釋放池中,自動釋放池結束的時候,會給釋放池中的每個對象發送一條release消息

使用:

1)自動創建釋放池

autoreleasepool{

}

2)加入自動釋放池,

在自動釋放池中

[對象 autorelease]

加入到自動釋放池中以后,引用計數器不會變化

 

基本用法總結

1.會將對象放到一個自動釋放池中

2.當自動釋放池被銷毀時,會對尺子里的所有對象做一次release操作

3.會返回對象本身

4.調用完autorelease方法后,對象的計數器不變。

 

int main(int argc, const char * argv[]) {    //1 創建自動釋放池    Person *p = [Person new];  // p  1    @autoreleasepool {//自動釋放池開始                [p run];         NSLog(@"%lu",p.retainCount); // 1                // [p autorelease] 把對象p加入到自動釋放池中        // 注意:加入到自動釋放池中以后, 引用計數不會變化        [p autorelease];  //加入自動釋放池,        NSLog(@"%lu",p.retainCount); // 1                [p run];            }//自動釋放池結束   [p release];    [p run];    return 0;}

 

 

 

注意及錯誤用法:

1)并不是放到自動釋放池中的代碼產生的對象就會自動釋放,如果需要釋放,必須自動加入到自動釋放池

2)如果對象調用了autorelease但是調用autorelease的時候,沒有在任何一個自動釋放池中,此時該對象也不會被加入到自動釋放池

3)我們只需要在自動釋放池代碼塊中調用autorelease就可以把對象加入到自動釋放池

4)內存較大盡量不要使用autorelease

 

自動釋放池嵌套使用

 

為什么內存管理只管理內存對象?

堆中內存不連續,無法自動釋放!

 

我們如何對內存對象進行管理!

通過操作對象的引用計數器

 

autorelease的應用場景 

經常用來在類方法中快速創建一個對象

 

 
ARC
指針分類
(1)強指針:默認情況下所有指針都是強指針  關鍵字__strong
(2)弱指針:__weak關鍵字修飾的指針
 
原則 :當開啟ARC時,編譯器將自動在代碼合適的地方插入retain、release、autorelease.
          永遠不要寫retain、release、autorelease;
 
判斷準則:只要沒有強指針,對象就會被釋放
 
ARC機制:

1)判斷是否是ARC機制

查看項目信息,不能使用retain release和autorelease,retainCount ,不能調用[super dealloc]

2)使用

正常創建對象,不用手動釋放對象

ARC下單對象內存管理

  ARC機制下,對象沒有被強指針指向,對象會立即釋放空間

(兩個下劃線)__strong 修飾的指針是強指針,可以不寫 

                 __weak 修飾的指針是弱指針

 1) 強指針指向了其他內容,對于對象來說就沒有強指針指向了

 2) 弱指針賦值為nil

 

ARC下多對象的內存管理 

 

ARC機制下不能使用retain 應該使用strong 和 weak

ARC下循環引用問題

循環引用時一端使用strong , 一端使用weak.

 

ARC下set方法內存和@property參數

  原子性/讀寫 和MRC下一樣

 MRC            ARC

assign         assign 適用于非oc對象

retain         strong(強指針) OC的其他對象  weak (成員變量是弱指針適用于oc對象)

copy            copy

 

ARC使用特點及注意事項

  特點: 

1) 不允許調用retain release、retainCount

2) 允許重寫dealloc,但是不能調用[super dealloc] 

 

注意事項:

  1)ARC中,只要弱指針對象不存在,直接把弱指針清空(賦值nil)操作

  2)__weak Person *p = [Person new]

弱指針指向空間銷毀過程: (1)釋放對象空間  (2)指針賦值nil

 

 

 

 

MRC轉換為ARC

edit->Refactor->convert to Objective-C ARC…簡單代碼

ARC兼容非ARC的類

 轉變為非ARC   -fno-objc-arc

 轉變為ARC的    -f-objc-arc

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临夏市| 尤溪县| 林芝县| 定南县| 信阳市| 沿河| 县级市| 松原市| 罗甸县| 鸡西市| 漠河县| 磐石市| 盘锦市| 朝阳市| 永昌县| 新密市| 通州区| 陕西省| 永丰县| 禄丰县| 江源县| 怀集县| 同江市| 万荣县| 临海市| 桂平市| 绵阳市| 卓资县| 砀山县| 陈巴尔虎旗| 洞头县| 房产| 千阳县| 南陵县| 佛学| 吉林市| 崇仁县| 永州市| 璧山县| 高雄市| 鄂托克旗|