国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【iOS】ARC內(nèi)存管理

這篇具有很好參考價(jià)值的文章主要介紹了【iOS】ARC內(nèi)存管理。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

內(nèi)存管理的思考方式

怎么說呢。經(jīng)典再放送咯。

對(duì)象操作 對(duì)應(yīng)的Objective-C方法
生成并持有對(duì)象 alloc/new/copy/mutableCopy等方法
持有對(duì)象 retain方法
釋放對(duì)象 release方法
廢棄對(duì)象 dealloc方法

iOS底層內(nèi)存管理方式

iOS內(nèi)存管理方案有三種,我們?cè)敿?xì)看下每種方案的實(shí)現(xiàn)及存在的意義。

1. tagged pointer

標(biāo)簽指針

沒有這種管理機(jī)制會(huì)引起內(nèi)存浪費(fèi),為什么呢?

我們來看下,假設(shè)我們要存儲(chǔ)一個(gè)NSNumber對(duì)象,其值是一個(gè)整數(shù)。正常情況下,如果這個(gè)整數(shù)只是一個(gè)NSInteger的普通變量,那么它所占用的內(nèi)存是與CPU的位數(shù)有關(guān),在32位CPU下占4個(gè)字節(jié),在64位CPU下是占8個(gè)字節(jié)的。而指針類型的大小通常也是與CPU位數(shù)相關(guān),一個(gè)指針?biāo)加玫膬?nèi)存在32位CPU下為4個(gè)字節(jié),在64位CPU下也是8個(gè)字節(jié)。

所以一個(gè)普通的iOS程序,如果沒有Tagged Pointer對(duì)象,從32位機(jī)器遷移到64位機(jī)器中后,雖然邏輯沒有任何變化,但這種NSNumber、NSDate一類的對(duì)象所占用的內(nèi)存會(huì)翻倍。如下圖所示:

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

我們?cè)賮砜纯葱噬系膯栴},為了存儲(chǔ)和訪問一個(gè)NSNumber對(duì)象,我們需要在堆上為其分配內(nèi)存,另外還要維護(hù)它的引用計(jì)數(shù),管理它的生命期。這些都給程序增加了額外的邏輯,造成運(yùn)行效率上的損失。

為了改進(jìn)上面提到的內(nèi)存占用和效率問題,蘋果提出了Tagged Pointer對(duì)象。由于NSNumberNSDate一類的變量本身的值需要占用的內(nèi)存大小常常不需要8個(gè)字節(jié),拿整數(shù)來說,4個(gè)字節(jié)所能表示的有符號(hào)整數(shù)就可以達(dá)到20多億(注:2^31=2147483648,另外1位作為符號(hào)位),對(duì)于絕大多數(shù)情況都是可以處理的。

所以我們可以將一個(gè)對(duì)象的指針拆成兩部分,一部分直接保存數(shù)據(jù),另一部分作為特殊標(biāo)記,表示這是一個(gè)特別的指針,不指向任何一個(gè)地址。所以,引入了Tagged Pointer對(duì)象之后,64位CPU下NSNumber的內(nèi)存圖變成了以下這樣:

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

當(dāng)8字節(jié)可以承載用于表示的數(shù)值時(shí),系統(tǒng)就會(huì)以Tagged Pointer的方式生成指針,如果8字節(jié)承載不了時(shí),則又用以前的方式來生成普通的指針。以上是關(guān)于Tag Pointer的存儲(chǔ)細(xì)節(jié)。
Tagged Pointer的特點(diǎn):

  • 我們也可以在WWDC2013的《Session 404 Advanced in Objective-C》視頻中,看到蘋果對(duì)于Tagged Pointer特點(diǎn)的介紹:Tagged Pointer專門用來存儲(chǔ)小的對(duì)象,例如NSNumberNSDate, 當(dāng)然NSString小于60字節(jié)的也可以運(yùn)用了該手段
  • Tagged Pointer指針的值不再是地址了,而是真正的值。所以,實(shí)際上它不再是一個(gè)對(duì)象了,它只是一個(gè)披著對(duì)象皮的普通變量而已,因?yàn)樗麤]有isa指針。所以,它的內(nèi)存并不存儲(chǔ)在堆中,也不需要mallocfree。
  • 在內(nèi)存讀取上有著3倍的效率,創(chuàng)建時(shí)比以前快106倍。

由此可見,蘋果引入Tagged Pointer,不但減少了64位機(jī)器下程序的內(nèi)存占用,還提高了運(yùn)行效率。完美地解決了小內(nèi)存對(duì)象在存儲(chǔ)和訪問效率上的問題。

2. non-pointer iSA–非指針型iSA

在64位系統(tǒng)上只需要32位來儲(chǔ)存內(nèi)存地址,而剩下的32位就可以用來做其他的內(nèi)存管理

non_pointer iSA 的判斷條件:

1 : 包含swift代碼;

2:sdk版本低于10.11;

3:runtime讀取image時(shí)發(fā)現(xiàn)這個(gè)image包含__objc_rawi sa段;

4:開發(fā)者自己添加了OBJC_DISABLE_NONPOINTER_ISA=YES到環(huán)境變量中;

5:某些不能使用Non-pointer的類,GCD等;

6:父類關(guān)閉。

3. SideTables,RefcountMap,weak_table_t

為了管理所有對(duì)象的引用計(jì)數(shù)和weak指針,蘋果創(chuàng)建了一個(gè)全局的SideTables,雖然名字后面有個(gè)"s"不過他其實(shí)是一個(gè)全局的Hash表,里面的內(nèi)容裝的都是SideTable結(jié)構(gòu)體而已。它使用對(duì)象的內(nèi)存地址當(dāng)它的key。管理引用計(jì)數(shù)和weak指針就靠它了。

因?yàn)閷?duì)象引用計(jì)數(shù)相關(guān)操作應(yīng)該是原子性的。不然如果多個(gè)線程同時(shí)去寫一個(gè)對(duì)象的引用計(jì)數(shù),那就會(huì)造成數(shù)據(jù)錯(cuò)亂,失去了內(nèi)存管理的意義。同時(shí)又因?yàn)閮?nèi)存中對(duì)象的數(shù)量是非常非常龐大的需要非常頻繁的操作SideTables,所以不能對(duì)整個(gè)Hash表加鎖。蘋果采用了分離鎖技術(shù)。

下邊是SideTabel的定義:

SideTable
   struct SideTable {
     //鎖
     spinlock_t slock;
     //強(qiáng)引用相關(guān)
     RefcountMap refcnts;
     //弱引用相關(guān)
     weak_table_t weak_table;
     ...
}

當(dāng)我們通過SideTables[key]來得到SideTable的時(shí)候,SideTable的結(jié)構(gòu)如下:

1、一把自旋鎖。spinlock_t slock;

自旋鎖比較適用于鎖使用者保持鎖時(shí)間比較短的情況。正是由于自旋鎖使用者一般保持鎖時(shí)間非常短,因此選擇自旋而不是睡眠是非常必要的,自旋鎖的效率遠(yuǎn)高于互斥鎖。信號(hào)量和讀寫信號(hào)量適合于保持時(shí)間較長的情況,它們會(huì)導(dǎo)致調(diào)用者睡眠,因此只能在進(jìn)程上下文使用,而自旋鎖適合于保持時(shí)間非常短的情況,它可以在任何上下文使用。

它的作用是在操作引用計(jì)數(shù)的時(shí)候?qū)?code>SideTable加鎖,避免數(shù)據(jù)錯(cuò)誤。

蘋果在對(duì)鎖的選擇上可以說是精益求精。蘋果知道對(duì)于引用計(jì)數(shù)的操作其實(shí)是非??斓?。所以選擇了雖然不是那么高級(jí)但是確實(shí)效率高的自旋鎖。

2、引用計(jì)數(shù)器 RefcountMap * refcnts;

對(duì)象具體的引用計(jì)數(shù)數(shù)量是記錄在這里的。

這里注意RefcountMap其實(shí)是個(gè)C++的Map。為什么Hash以后還需要個(gè)Map呢?因?yàn)閮?nèi)存中對(duì)象的數(shù)量實(shí)在是太龐大了我們通過第一個(gè)Hash表只是過濾了第一次,然后我們還需要再通過這個(gè)Map才能精確的定位到我們要找的對(duì)象的引用計(jì)數(shù)器。

引用計(jì)數(shù)器的數(shù)據(jù)類型是:

typedef __darwin_size_t size_t;

再進(jìn)一步看它的定義其實(shí)是unsigned long,在32位和64位操作系統(tǒng)中,它分別占用32和64個(gè)bit。

蘋果經(jīng)常使用bit mask技術(shù)。這里也不例外。拿32位系統(tǒng)為例的話,可以理解成有32個(gè)盒子排成一排橫著放在你面前。盒子里可以裝0或者1兩個(gè)數(shù)字。我們規(guī)定最后邊的盒子是低位,左邊的盒子是高位。

(1UL<<0)的意思是將一個(gè)"1"放到最右側(cè)的盒子里,然后將這個(gè)"1"向左移動(dòng)0位(就是原地不動(dòng)):0b0000 0000 0000 0000 0000 0000 0000 0001

(1UL<<1)的意思是將一個(gè)"1"放到最右側(cè)的盒子里,然后將這個(gè)"1"向左移動(dòng)1位:0b0000 0000 0000 0000 0000 0000 0000 0010

下面來分析引用計(jì)數(shù)器(圖中右側(cè))的結(jié)構(gòu),從低位到高位。

(1UL<<0)???WEAKLY_REFERENCED

表示是否有弱引用指向這個(gè)對(duì)象,如果有的話(值為1)在對(duì)象釋放的時(shí)候需要把所有指向它的弱引用都變成nil(相當(dāng)于其他語言的NULL),避免野指針錯(cuò)誤。

(1UL<<1)???DEALLOCATING

表示對(duì)象是否正在被釋放。1正在釋放,0沒有

(1UL<<(WORD_BITS-1))???SIDE_TABLE_RC_PINNED

其中WORD_BITS在32位和64位系統(tǒng)的時(shí)候分別等于32和64。其實(shí)這一位沒啥具體意義,就是隨著對(duì)象的引用計(jì)數(shù)不斷變大。如果這一位都變成1了,就表示引用計(jì)數(shù)已經(jīng)最大了不能再增加了。

3、維護(hù)weak指針的結(jié)構(gòu)體 weak_table_t * weak_table;

第一層結(jié)構(gòu)體中包含兩個(gè)元素。

第一個(gè)元素weak_entry_t *weak_entries;是一個(gè)數(shù)組,上面RefcountMap是要通過find(key)來找到精確的元素的。weak_entries則是通過循環(huán)遍歷來找到對(duì)應(yīng)的entry

(上面管理引用計(jì)數(shù)器蘋果使用的是Map,這里管理weak指針蘋果使用的是數(shù)組,有興趣的朋友可以思考一下為什么蘋果會(huì)分別采用這兩種不同的結(jié)構(gòu))

這個(gè)是因?yàn)?code>weak的顯著的特征來決定的: 當(dāng)weak對(duì)象被銷毀的時(shí)候,要把所有指向該對(duì)象的指針都設(shè)為nil。

第二個(gè)元素num_entries是用來維護(hù)保證數(shù)組始終有一個(gè)合適的size。比如數(shù)組中元素的數(shù)量超過3/4的時(shí)候?qū)?shù)組的大小乘以2。

第二層weak_entry_t的結(jié)構(gòu)包含3個(gè)部分:

1、referent:被指對(duì)象的地址。前面循環(huán)遍歷查找的時(shí)候就是判斷目標(biāo)地址是否和他相等。
2、referrers:可變數(shù)組,里面保存著所有指向這個(gè)對(duì)象的弱引用的地址。當(dāng)這個(gè)對(duì)象被釋放的時(shí)候,referrers里的所有指針都會(huì)被設(shè)置成nil。
3、inline_referrers只有4個(gè)元素的數(shù)組,默認(rèn)情況下用它來存儲(chǔ)弱引用的指針。當(dāng)大于4個(gè)的時(shí)候使用referrers來存儲(chǔ)指針。

上面我們介紹了蘋果為了更好的內(nèi)存管理使用的三種不同的內(nèi)存管理方案,在內(nèi)部采用了不同的數(shù)據(jù)結(jié)構(gòu)以達(dá)到更高效內(nèi)存檢索。

內(nèi)存管理有關(guān)修飾符

__strong修飾符

__strong修飾符是id類型和對(duì)象類型默認(rèn)的所有權(quán)修飾符。

不論調(diào)用哪種方法,強(qiáng)引用修飾的變量會(huì)持有該對(duì)象,如果已經(jīng)持有則引用計(jì)數(shù)不會(huì)增加。

對(duì)象的所有者和對(duì)象的生命周期

  1. 持有強(qiáng)引用的變量在超出其作用域時(shí)被廢棄
  2. 隨著強(qiáng)引用的失效,引用的對(duì)象會(huì)隨之釋放

__strong對(duì)象相互賦值

__strong修飾符的變量不僅只在變量作用域中,在賦值上也能夠正確的管理其對(duì)象的所有者。

id __strong obj0 = [[NSObject alloc] init];//生成對(duì)象A			
id __strong obj1 = [[NSObject alloc] init];//生成對(duì)象B		
id __strong obj2 = nil;
obj0 = obj1;//obj0強(qiáng)引用對(duì)象B;而對(duì)象A不再被ojb0引用,被廢棄
obj2 = obj0;//obj2強(qiáng)引用對(duì)象B(現(xiàn)在obj0,ojb1,obj2都強(qiáng)引用對(duì)象B)	
obj1 = nil;//obj1不再強(qiáng)引用對(duì)象B	
obj0 = nil;//obj0不再強(qiáng)引用對(duì)象B	
obj2 = nil;//obj2不再強(qiáng)引用對(duì)象B,不再有任何強(qiáng)引用引用對(duì)象B,對(duì)象B被廢棄

方法參數(shù)中使用__strong

廢棄Test對(duì)象的同時(shí),Test對(duì)象的obj_成員變量也被廢除
即成員變量的生存周期是與對(duì)象同步的。

__strong導(dǎo)致的循環(huán)引用

循環(huán)引用就是兩個(gè)對(duì)象相互引用導(dǎo)致在該釋放的時(shí)候沒有釋放,從而一直占著內(nèi)存導(dǎo)致內(nèi)存泄漏

內(nèi)存泄漏:在內(nèi)存該被釋放的時(shí)候沒有釋放,導(dǎo)致內(nèi)存被浪費(fèi)使用了

舉個(gè)例子:

#import <Foundation/Foundation.h>

@interface StrongTest : NSObject {
    id __strong _obj;
}
- (void) setObject:(id __strong) obj;

@end

#import "StrongTest.h"
@implementation StrongTest
- (void) setObject:(id)obj {
    _obj = obj;
}
@end

main函數(shù):

#import <Foundation/Foundation.h>
#import "StrongTest.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        StrongTest *testFirst = [[StrongTest alloc] init];//生成Test1
        StrongTest *testSecond = [[StrongTest alloc] init];//生成Test2
        
        [testFirst setObject:testSecond];
        [testSecond setObject:testFirst];
        
        //打印一下引用計(jì)數(shù)值
        NSLog(@"%lu", CFGetRetainCount((__bridge  CFTypeRef)testFirst));       
    }
    return 0;
}

我們創(chuàng)建了兩個(gè)對(duì)象testFirsttestSecond
每個(gè)對(duì)象內(nèi)部都有一個(gè)成員變量_obj
其中一個(gè)對(duì)象的_obj持有另一個(gè)對(duì)象

最后就會(huì)造成下面的結(jié)果:

testFirst持有Test1,testFirst.obj持有Test2,testSecond持有Test2testSecond.obj持有Test1

失效階段的表示:

what happen Test1引用計(jì)數(shù) Test1持有者 Test2引用計(jì)數(shù) Test2持有者
初始狀態(tài) 2 testFirst, testSecond.obj 2 testFirst.obj, testSecond
testFirst超出作用域 1 testSecond.obj 2 testFirst.obj, testSecond
testSecond超出作用域 1 testSecond.obj 1 testFirst.obj

這樣一來,即使兩個(gè)對(duì)象的指針都超出作用域,由于其中彼此的成員變量相互持有彼此的對(duì)象而造成循環(huán)引用。

__weak修飾符

__weak弱引用(引用計(jì)數(shù)不會(huì)加一 對(duì)象隨時(shí)可能會(huì)被dealloc)
內(nèi)部使用__autoreleasing來維持該對(duì)象不被dealloc(這個(gè)也是__weak修飾符修飾的對(duì)象在所指向的對(duì)象銷毀之后會(huì)自動(dòng)指向nil的關(guān)鍵所在)
對(duì)象的引用計(jì)數(shù)是記錄在一張表上的,不在對(duì)象本身或者指針中,系統(tǒng)通過訪問這張表來確定是否釋放該對(duì)象。

將上面相互引用例子中的成員變量變?yōu)閣eak,即可避免循環(huán)引用。

weak還有個(gè)作用。在持有某對(duì)象的弱引用時(shí),若該對(duì)象被廢棄,則此若引用將自動(dòng)失效且處于nil被賦值的狀態(tài)(空弱引用)。

weak提供弱引用,弱引用不持有對(duì)象,NSObject對(duì)象會(huì)被銷毀,所以會(huì)報(bào)一個(gè)警告

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

我們可以這樣使用__weak修飾符的變量,將__strong修飾的對(duì)象賦值給__weak修飾的對(duì)象,這樣就不會(huì)發(fā)生警告了:

	id __strong objTest = [[NSObject alloc] init];
    id __weak objTestSecond = objTest;

類似于“強(qiáng)弱共舞”

__weak修飾符的引用計(jì)數(shù)的問題

按以下例子,我們來看一下這兩個(gè)的引用計(jì)數(shù)的值:

    id __strong obj = [[NSObject alloc] init];
    id __weak objTest = obj;
    NSLog(@"%lu", CFGetRetainCount((__bridge  CFTypeRef)obj));
    NSLog(@"%lu", CFGetRetainCount((__bridge  CFTypeRef)objTest));

按照常理來說應(yīng)該是1 1,因?yàn)開_weak修飾符不持有對(duì)象,引用計(jì)數(shù)值兩個(gè)都應(yīng)該是1

打印一下結(jié)果:

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

對(duì)比一下就能發(fā)現(xiàn) 兩行NSLog的匯編代碼并不一樣

第二個(gè)__weak修飾符的NSLog在于開始先loadWeakRetained
然后在打印結(jié)束后有一個(gè)release操作

在打印__weak的引用計(jì)數(shù)時(shí)NSLog先將其以強(qiáng)引用,防止沒有打印就釋放掉了造成程序的崩潰,在NSLog結(jié)束時(shí),會(huì)調(diào)用objc_release使引用計(jì)數(shù)減一。

__unsafe_unretained

__unsafe_unretained修飾符正如其名unsafe所示,是不安全的所有權(quán)修飾符。
附有__unsafe_unretained修飾符的變量不屬于編譯器的內(nèi)存管理對(duì)象。

為什么是不安全的呢

weak 修飾的指針變量,在指向的內(nèi)存地址銷毀后,會(huì)在 Runtime 的機(jī)制下,自動(dòng)置為 nil。 _unsafe_unretain 不會(huì)置為 nil,容易出現(xiàn) 懸垂指針,發(fā)生崩潰。但是 __unsafe_unretain __weak 效率高。
懸垂指針 指針指向的內(nèi)存已經(jīng)被釋放了,但是指針還存在,這就是一個(gè) 懸垂指針 或者說 迷途指針。野指針,沒有進(jìn)行初始化的指針,其實(shí)都是 野指針

附有__unsafe_unretained修飾符的變量同附有__weak修飾符的變量一樣,生成的對(duì)象會(huì)立即釋放。

在使用__unsafe_unretained修飾符時(shí),賦值給附有__strong修飾符的變量時(shí)有必要確保被賦值的對(duì)象確實(shí)存在,如果不存在,那么程序就會(huì)崩潰。

__autoreleasing修飾符

與MRC進(jìn)行比較:
MRC中autorelease的使用方法:

  1. 生成并持有NSAutoreleasePool對(duì)象
  2. 調(diào)用已分配對(duì)象的autorelease方法(將對(duì)象注冊(cè)到pool中)
  3. 廢棄NSAutoreleasePool對(duì)象

在ARC環(huán)境下:

NSAutoreleasePool *pool = [NSAutoreleasePool alloc] init]; 1??
[obj autorelease]; 2??
[pool drain]; 3??

等價(jià)于:

@autoreleasepool{ 1??
id __autorelease obj2; obj2 = obj; 2??
} 3??

自動(dòng)調(diào)用:

編譯器會(huì)檢查方法名是否以alloc/new/copy/mutableCopy開始,如果不是將自動(dòng)把返回值的對(duì)象注冊(cè)到autoreleasepool

下面情況不使用__autoreleasing修飾符也能使對(duì)象注冊(cè)到autoreleasepool中。

+ (id) array {
	return [[NSMutableArray alloc]init];
}

//如下:
+ (id) array {
	id obj = [[NSMutableArray alloc]init];
	return obj;
}

由于return使得對(duì)象變量超出其作用域,所以該強(qiáng)引用對(duì)應(yīng)的自己持有的對(duì)象會(huì)被自動(dòng)釋放,但該對(duì)象作為函數(shù)的返回值,編譯器也會(huì)自動(dòng)注冊(cè)到自動(dòng)釋放池

自動(dòng)調(diào)用時(shí)的失效過程:

隨著obj超出其作用域,強(qiáng)引用失效,所以自動(dòng)釋放自己持有的對(duì)象。
同時(shí),隨著@autoreleasepool塊的結(jié)束,注冊(cè)到autoreleasepool中的所有對(duì)象被自動(dòng)釋放。 因?yàn)閷?duì)象的擁有者不存在,所以廢棄對(duì)象。

weak修飾符與autoreleasing修飾符:

為什么訪問__weak修飾符的變量時(shí)必須訪問注冊(cè)到autoreleasepool的對(duì)象呢,這是因?yàn)?code>__weak修飾符只持有對(duì)象的弱引用,而在訪問引用對(duì)象的過程中,該對(duì)象有可能被廢棄。如果把要訪問的對(duì)象注冊(cè)到autoreleasepool中,那么在@autoreleasepool塊結(jié)束之前都能確保該對(duì)象存在,因此,在使用附有__weak修飾符的變量時(shí)就必定要使用注冊(cè)到autoreleasepool中的對(duì)象。

id __weak obj1 = obj0;
NSLog(@"class = %@", [obj1 class]);
與以下源代碼相同
id __weak obj1 = obj0;
id __autoreleasing tmp = obj1;
NSLog(@"class = %@", [temp class]);

例1

	//這個(gè)例子中obj0沒有加入到自動(dòng)釋放池中
    id  obj0 = [[NSObject alloc] init];
    id __weak obj1 = obj0;
    NSLog(@"class = %@", [obj1 class]);

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

池中沒有出現(xiàn)obj0。

例2

	//這個(gè)例子中obj0加入了自動(dòng)釋放池中
    id __autoreleasing obj0 = [[NSObject alloc] init];
    id __weak obj1 = obj0;
    NSLog(@"class = %@", [obj1 class]);

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

池中出現(xiàn)了obj0

例3

    id __autoreleasing obj0 = [[NSObject alloc] init];
    id __weak obj1 = obj0;
    id __autoreleasing obj2 = obj1;
    NSLog(@"class = %@", [obj2 class]);

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

池中出現(xiàn)了obj0,且看到count為2

例4

    id  obj0 = [[NSObject alloc] init];
    id __weak obj1 = obj0;
    id __autoreleasing obj2 = obj1;
    NSLog(@"class = %@", [obj2 class]);

【iOS】ARC內(nèi)存管理,ios,cocoa,macos

池中出現(xiàn)了obj0

總結(jié): __weak修飾符并不會(huì)將對(duì)象加入到自動(dòng)釋放池,但是我們使用__weak修飾的對(duì)象一定要是本身已經(jīng)加入到自動(dòng)釋放池的或者后續(xù)使用__autoreleasing將__weak所修飾的對(duì)象加入釋放池

具體ARC規(guī)則:

  • 不能使用retain/release/retainCount/autorelease
  • 不能使用NSAllocateObject/NSDeallocateObject
  • 必須遵守內(nèi)存管理的方法名規(guī)則
  • 不要顯式調(diào)用dealloc
  • 使用@autorelease塊代替NSAutoreleasePool
  • 不能使用區(qū)域(NSZone)
  • 對(duì)象型變量不能作為C語言結(jié)構(gòu)體的成員
  • 顯式轉(zhuǎn)換id和void*

重點(diǎn):

不能顯式調(diào)用dealloc

dealloc無法釋放不屬于該對(duì)象的一些東西,需要我們重寫時(shí)加上去,例如:文章來源地址http://www.zghlxwxcb.cn/news/detail-567706.html

  • 通知的觀察者,或KVO的觀察者
  • 對(duì)象強(qiáng)委托/引用的解除(例如XMPPMannerger的delegateQueue)
  • 做一些其他的注銷之類的操作(關(guān)閉程序運(yùn)行期間沒有關(guān)閉的資源)
In the implementation of dealloc, do not call the implementation of superclass. You should try to avoid using dealloc to manage the lifetime of limited resources, such as file descriptors.
You never send a dealloc message directly. Instead, the dealloc method of the object is called by the runtime.
在dealloc的實(shí)現(xiàn)中,不要調(diào)用超類的實(shí)現(xiàn)。您應(yīng)該盡量避免使用dealloc管理有限資源(如文件描述符)的生存期。
不要直接發(fā)送dealloc消息。與直接發(fā)送dealloc消息不同,對(duì)象的dealloc方法由運(yùn)行時(shí)調(diào)用。

Special Considerations
When not using ARC, your implementation of dealloc must invoke the superclass’s implementation as its last instruction.
特別注意事項(xiàng)
當(dāng)不使用ARC時(shí),dealloc的實(shí)現(xiàn)必須調(diào)用父類(super)的實(shí)現(xiàn)作為它的最后一條指令 [super dealloc]。

__bridge

  • bridge可以實(shí)現(xiàn)Objective-C與C語言變量和Objective-C與CoreFoundation對(duì)象之間的互相轉(zhuǎn)換
  • _bridge不會(huì)改變對(duì)象的持有狀況,既不會(huì)retain,也不會(huì)release
  • _bridge轉(zhuǎn)換需要慎重分析對(duì)象的持有情況,稍不注意就會(huì)內(nèi)存泄漏
  • _bridge_retained用于將口C變量轉(zhuǎn)換為C語言變量或?qū)C對(duì)象轉(zhuǎn)換為CoreFoundation對(duì)象
  • _bridge_retained類似于retain,“被轉(zhuǎn)換的變量”所持有的對(duì)象在變量賦值給"轉(zhuǎn)換目標(biāo)變量“后持有該對(duì)象
  • _bridge_transfer用于將C語言變量轉(zhuǎn)換為OC變量或?qū)?code>CoreFoundation對(duì)象轉(zhuǎn)換為OC對(duì)象
  • bridge_transfer類似于release,“被轉(zhuǎn)換的變量”所持有的對(duì)象在變量賦值給“轉(zhuǎn)換目標(biāo)變量”后隨衣釋熱

屬性關(guān)鍵字和所有權(quán)修飾符

屬性關(guān)鍵字 所有權(quán)修飾符
assign _unsafe_unretained
copy __strong
retain __strong
strong __strong
__unsafe_unretained __unsafe_unretained
weak __weak

到了這里,關(guān)于【iOS】ARC內(nèi)存管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【iOS內(nèi)存管理-內(nèi)存的幾大區(qū)域】

    【iOS內(nèi)存管理-內(nèi)存的幾大區(qū)域】

    iOS內(nèi)存管理的第一篇章,了解iOS內(nèi)存的五大分區(qū)。 iOS中,內(nèi)存主要分為五大區(qū)域:棧區(qū),堆區(qū),全局區(qū)/靜態(tài)區(qū),常量區(qū)和代碼區(qū)??傆[圖如下。 如上圖所示,代碼區(qū)是在低地址段存放,而棧區(qū)則存放在高地址段,并且各個(gè)分區(qū)之間不是連續(xù)的。 棧是 從高地址向低地址存儲(chǔ)

    2024年02月16日
    瀏覽(16)
  • 【iOS內(nèi)存管理-編譯鏈接的過程】

    【iOS內(nèi)存管理-編譯鏈接的過程】

    就我而言,iOS開發(fā)的過程中接觸到的編譯鏈接方面的知識(shí)很少,這部分知識(shí)還是很重要的。 對(duì)于iOS的編譯鏈接過程來說并不難,和微機(jī)原理的匯編過程還是挺像的。今天對(duì)于編譯鏈接的過程學(xué)習(xí)和了解一下。 參考:iOS程序員的自我修養(yǎng)-編譯、鏈接過程 參考:iOS編譯過程 計(jì)

    2024年02月16日
    瀏覽(20)
  • 初識(shí)FreeRTOS入門,對(duì)FreeRTOS簡(jiǎn)介、任務(wù)調(diào)度、內(nèi)存管理、通信機(jī)制以及IO操作,控制兩個(gè)led不同頻率閃爍

    當(dāng)代嵌入式系統(tǒng)的開發(fā)越來越復(fù)雜,實(shí)時(shí)性要求也越來越高。為了滿足這些需求,開發(fā)者需要使用實(shí)時(shí)操作系統(tǒng)(RTOS),其中一個(gè)流行的選擇是FreeRTOS(Free Real-Time Operating System)。本篇博客將詳細(xì)介紹FreeRTOS的特性、任務(wù)調(diào)度、內(nèi)存管理、通信機(jī)制以及一些示例代碼。 FreeR

    2024年02月14日
    瀏覽(20)
  • macos編譯libtiff庫給IOS用

    macos編譯libtiff庫給IOS用

    ? ? ?

    2024年02月12日
    瀏覽(19)
  • Charles證書過期解決方法macos/ios

    Charles證書過期解決方法macos/ios

    今天心血來潮打開Charles想試試看抓包手機(jī)APP(ios),結(jié)果發(fā)現(xiàn)各種x和提示ssl錯(cuò)誤。開始以為是和魔法的代理沖突或者ip變了,捯飭很久后發(fā)現(xiàn)web的也報(bào)錯(cuò)。 然后搜了一會(huì)原因發(fā)現(xiàn)時(shí)證書過期了 1、搜索“鑰匙串訪問”,直接搜索“charles”,找到打叉的名稱,直接刪掉 2、打開

    2024年02月03日
    瀏覽(23)
  • MacOS 14 系統(tǒng) XCode15、 Flutter 開發(fā) IOS

    MacOS 14 系統(tǒng) XCode15、 Flutter 開發(fā) IOS

    MacOS14 Sonoma 安裝 Flutter 開發(fā)環(huán)境 MacOS 系統(tǒng) Flutter開發(fā)Android 環(huán)境配置 MacOS 系統(tǒng) Flutter開發(fā)IOS 環(huán)境配置??????? 前面我們已經(jīng)在MacOS14 M3芯片上安裝好 Flutter環(huán)境,包括開發(fā)工具 VsCode 、Android Stuiod,那么flutter如何開發(fā)IOS呢? 我們知道IOS開發(fā)語言為 objcet-c或者 swift,F(xiàn)lutter是

    2024年02月03日
    瀏覽(23)
  • macOS Sonoma編譯OpenCV源碼輸出IOS平臺(tái)庫

    macOS Sonoma編譯OpenCV源碼輸出IOS平臺(tái)庫

    1.macOS下載并編譯OpenCV源碼:? 克隆源碼: 主倉:?git clone https://github.com/opencv/opencv.git 擴(kuò)展倉:? git clone https://github.com/opencv/opencv_contrib.git ? ?編譯xcode源碼需要CMake與XCode命令行工具 確認(rèn)已安裝CMake ?確認(rèn)已安裝XCode ?安裝xcode command line tools 確認(rèn)系統(tǒng)已安裝python環(huán)境

    2024年02月10日
    瀏覽(18)
  • macos搭建appium-iOS自動(dòng)化測(cè)試環(huán)境

    macos搭建appium-iOS自動(dòng)化測(cè)試環(huán)境

    目錄 準(zhǔn)備工作 安裝必需的軟件 安裝appium 安裝XCode 下載WDA工程 配置WDA工程 搭建appium+wda自動(dòng)化環(huán)境 第一步:?jiǎn)?dòng)通過xcodebuild命令啟動(dòng)wda服務(wù) 分享一下如何在mac電腦上搭建一個(gè)完整的appium自動(dòng)化測(cè)試環(huán)境 前期需要準(zhǔn)備的設(shè)備和賬號(hào): mac電腦一臺(tái) iphone一臺(tái) 蘋果開發(fā)者賬號(hào)一

    2024年02月13日
    瀏覽(22)
  • uniapp打包之配置MacOS虛擬機(jī)生成iOS打包證書

    uniapp打包之配置MacOS虛擬機(jī)生成iOS打包證書

    uniapp是一款跨端開發(fā)框架,可用于快速開發(fā)iOS、Android、H5等多端應(yīng)用。本文將詳細(xì)介紹如何實(shí)現(xiàn)uniapp開發(fā)的iOS應(yīng)用打包。 一、下載蘋果原版鏡像文件 點(diǎn)擊此處下載 二、安裝VMware uniapp打包iOS應(yīng)用需要生成相應(yīng)證書和P2文件,這些都需要用到IOS環(huán)境,這里我是使用的是MacOS虛擬機(jī)

    2024年02月12日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包