溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Objective-C(7)內(nèi)存管理之MRC

發(fā)布時(shí)間:2020-07-17 16:01:25 來(lái)源:網(wǎng)絡(luò) 閱讀:549 作者:ymanmeng123 欄目:移動(dòng)開發(fā)
  • Objective-C內(nèi)存管理

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

每個(gè)計(jì)算機(jī)系統(tǒng)可供程序使用的內(nèi)存資源是有限的。我們要關(guān)心兩件事情:

     在需要時(shí)分配,用完之后釋放

     不要使用任何已被釋放的內(nèi)存資源,否則將無(wú)用陳舊的值導(dǎo)致各種各樣的錯(cuò)誤發(fā)生

三種管理方式:

    手動(dòng)管理方式 MRC(Manual referencing count)

    半自動(dòng)管理方式  autoreleasepool

    自動(dòng)管理方式 ARC(Auto referencing count)


  • 引用計(jì)數(shù)與內(nèi)存管理準(zhǔn)則

Cocoa采用了一種稱為“引用計(jì)數(shù)”的技術(shù),它為每個(gè)對(duì)象關(guān)聯(lián)一個(gè)整數(shù):

相關(guān)方法:

- (instancetype)retain          //引用計(jì)數(shù)+1
- (void)release                 //引用計(jì)數(shù)-1
- (NSUInteger)retainCount       //對(duì)象的當(dāng)前引用計(jì)數(shù)值

使用引用計(jì)數(shù):

     a. 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)(alloc new copy),被創(chuàng)建對(duì)象的引用計(jì)數(shù)為1

     b. 當(dāng)某段代碼要訪問(wèn)這個(gè)對(duì)象時(shí)就對(duì)該引用計(jì)數(shù)+1 (retain)

     c. 當(dāng)這段代碼完成后要對(duì)這個(gè)引用計(jì)數(shù)-1 (release)

     d. 當(dāng)引用計(jì)數(shù)為0時(shí),表示沒(méi)有代碼訪問(wèn)這個(gè)對(duì)象了,該對(duì)象就會(huì)被銷毀

     (銷毀前自動(dòng)向其發(fā)送一個(gè)dealloc消息)。


場(chǎng)景解釋:游戲中的房間、副本等


內(nèi)存管理的準(zhǔn)則:

1)內(nèi)存管理的原則:

     只要還有人在使用某個(gè)對(duì)象,那么這個(gè)對(duì)象就不會(huì)被回收;

     只要你想使用這個(gè)對(duì)象,那么就應(yīng)該讓這個(gè)對(duì)象的引用計(jì)數(shù)器+1;

     當(dāng)你不想使用這個(gè)對(duì)象時(shí),應(yīng)該讓對(duì)象的引用計(jì)數(shù)器-1;

2)誰(shuí)創(chuàng)建,誰(shuí)release

     a. 如果你通過(guò)alloc,new,copy來(lái)創(chuàng)建了一個(gè)對(duì)象,那么你就必須調(diào)用release或者autorelease方法

     b. 不是你創(chuàng)建的就不用你去負(fù)責(zé)

3)誰(shuí)retain,誰(shuí)release

總結(jié):有始有終,有加有減。


  • MRC中的代碼規(guī)范

1)只要調(diào)用了alloc,就必須有release

2)屬性的setter方法

     a. 基本數(shù)據(jù)類型直接賦值

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


     b. OC對(duì)象,先判斷和屬性舊值的是不是同一對(duì)象

          如果是,則什么也不做;如果不是,將舊值release,并對(duì)新值retain

- (void) setCar:(Car *) car {
    if ( car != _car ) {
         [ _car release];
         _car = [ car retain];
    }
}


3)dealloc方法

     a. 對(duì)self所持有的屬性release一次

     b. [super dealloc]放在最后

- (void) dealloc {
    [car release];
    [super dealloc];
}


4)不要出現(xiàn)以下垃圾代碼

stu.car = [[Car alloc] init];      //會(huì)使引用計(jì)數(shù)為2
[[Car alloc] init].speed = 100;  //無(wú)法釋放了


  • @property的內(nèi)存管理參數(shù)

@property應(yīng)有且僅有一個(gè)內(nèi)存管理參數(shù)。

MRC下,內(nèi)存管理參數(shù)包括:assign  retain  copy,默認(rèn)為assign

這些內(nèi)存管理參數(shù),能夠決定屬性setter方法的實(shí)現(xiàn)

assign:setter不修改引用計(jì)數(shù)

@property (nonatomic,assign) NSInteger age;

     setter方法:

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

retain:修改該屬性的引用計(jì)數(shù)(按照代碼規(guī)范)

@property (nonatomic, retain) NSNumber * age;

     setter方法:

- (void)setAge:(NSNumber *)age {
    if ( _age != age ) {
       [_age release];
       _age = [age retain];
    }
}


copy:深拷貝賦值,一般用于NSString

@property (nonatomic, copy) NSString * name;

     setter方法:

- (void)setName:(NSString *)name {
   if ( _name != nil ) {
       [_name release];
   }
   _name = [name copy];
}

對(duì)象復(fù)合關(guān)系出現(xiàn)的循環(huán)引用問(wèn)題

問(wèn)題描述:

     一個(gè)Person對(duì)象,一個(gè)Card對(duì)象,互為屬性

     如果一個(gè)內(nèi)存參數(shù)均為retain,則應(yīng)會(huì)使引用計(jì)數(shù)均為2

     這樣做對(duì)任意對(duì)象release,都不會(huì)使對(duì)象銷毀

解決方法:

     一端使用retain,一端使用assign



向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI