日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OC语言学习记录

發布時間:2023/12/31 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OC语言学习记录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、主要的OC的基本類型介紹

二、IOS屬性

1、什么是屬性

2、屬性修飾符

A、讀寫性修飾符

B、原子性修飾符

C、assgin和weak

D、strong和copy

E、retain

三、iOS內存管理

1、什么是內存管理?

2、內存是怎么分配的,是分配在哪里的?

3、什么是引用計數

?4、MRC手動管理引用計數

5、ARC自動管理引用計數

7、Core Foundation 對象的內存管理

?四、參考文檔


本文檔是作者自學的總結文檔,如有侵權,請聯系作者,作者進行刪除文檔

一、主要的OC的基本類型介紹

OC的數據類型有:
字符串,浮點型,整型,布爾類型 而且OC的數組也分為可變數組和不可變數組 OC的詞典也分為可變詞典和不可變詞典

二、IOS屬性

1、什么是屬性

屬性是OC語言的一個機制,我們在OC中用@property來聲明的一個屬性,其實@property是一種語法糖,編譯器會自動為你的實例變量生成getter方法和setter方法。

2、屬性修飾符

A、讀寫性修飾符

(1)readwrite

表明這個屬性是可讀可寫,是系統默認屬性,系統為我們創建setter和getter方法。

(2)readonly

表明這個屬性只可讀不能寫,系統只為我們創建getter方法,不會創建setter方法。

B、原子性修飾符

(1)atomic

原子屬性,線程安全但可能降低性能。

(2)nonatomic

非原子屬性,提高性能但非線程安全。

C、assgin和weak

weak與assgin都表示了一種非持有關系,也不被稱為弱引用,在調用時,不會增加引用對象的引用計數。weak在引用對象被銷毀時,會被指向nil;而assgin不會被置為nil。

(1)assign

如果用assgin修飾對象,當assgin指向的對象被銷毀時,assgin就會指向一塊無效內存(變成懸空指針),如果這個時候你給assgin發送消息,程序就會發生崩潰,也有可能不會崩潰,這個取決于你發送消息時,那塊內存還是否存在。

assgin一般修飾的基礎數據類型(NSInteger,int,float,double,char,bool等),因為基礎數據類型是被分配到棧上,棧的內存會由系統自動處理,所以不會造成懸空指針。

(2)weak

只用于修飾對象。

D、strong和copy

使用strong和copy是都會使引用對象引用計數+1。但是使用copy修飾的屬性在某些情況下賦值的時候會創建對象的副本,就是深拷貝。strong是兩個指針指向同一個內存地址,copy是在內存中拷貝一份對象,兩個指針指向不同的內存地址。

(1)copy

copy修飾NSString、NSArray、block屬性。我們以為copy只是深拷貝,其實不是的,系統在當源字符串為不可變類型時,你的屬性copy其實就是進行淺拷貝,當源字符串為可變類型時,才進行深拷貝。但是我們建議在使用NSString屬性的時候用copy,避免可變字符額修改導致一些非預期問題。

注:

1、對不可變對象執行copy操作,是淺拷貝(指針拷貝,內容相同),都指向同一邊存儲空間,源數據被修改,副本數據也會被修改

2、對不可變字符串執行mutCopy操作,是深拷貝(對象拷貝),兩者指向不同的存儲空間

3、可變字符串執行copy或mutCopy都是深拷貝

4、可變容器類執行copy或mutcopy或者不可變容器執行mutCopy都是不完全深拷貝,即只是容器對象指向不同的內存空間,內部的元素則指向同一個內存

5、可變數組執行copy(NSMutableArray執行copy后返回的NSArray),在使用過程回出現crash的問題

6、數組完全深拷貝需要執行initWithArray:copyItems: 方法 NSArray *deepCopy = [[NSArray alloc] initWithArray:array copyItems:YES];

(2)strong

strong修飾NSString、block以外的OC對象。

注:

strong與copy的區別:

(1)當原字符串是NSString時,由于是不可變字符串,所以,不管使用strong還是copy修飾,都是指向原來的對象,copy操作只是做了一次淺拷貝。

(2)當源字符串是NSMutableString時,strong只是將源字符串的引用計數加1,而copy則是對原字符串做了次深拷貝,從而生成了一個新的對象,并且copy的對象指向這個新對象。

所以,如果源字符串是NSMutableString的時候,使用strong只會增加引用計數。但是copy會執行一次深拷貝,會造成不必要的內存浪費。而如果原字符串是NSString時,strong和copy效果一樣,就不會有這個問題。

但是,我們一般聲明NSString時,也不希望它改變,所以一般情況下,建議使用copy,這樣可以避免NSMutableString帶來的錯誤。

strong與copy的區別

E、retain

retain修飾NSArray,NSDate。對應的setter方法。

與assign相對,我們要解決對象被其他對象引用后釋放造成的問題,就要用retain來聲明。retain聲明后的對象會更改引用計數,那么每次被引用,引用計數都會+1,釋放后就會-1,即使這個對象本身釋放了,只要還有對象在引用它,就會持有,不會造成什么問題,只有當引用計數為0時,就被dealloc析構函數回收內存了。

IOS屬性

IOS深拷貝和淺拷貝

三、iOS內存管理

1、什么是內存管理?

內存管理是指軟件運行時對計算機內存資源的分配和使用的技術。其最主要的目的是如何高效、快速的分配,并且在適當的時候釋放和回收內存資源。

2、內存是怎么分配的,是分配在哪里的?

在IOS中數據是存在堆和棧中的,然而我們的內存管理是管理堆上的內存,棧上的內存并不需要我們管理(計算機會自動回收)。

  • 基礎數據類型(非OC對象)存儲在棧上
  • OC對象存儲在堆上
int a = 10; //棧 int b = 20; //棧 Car *c = [[Car alloc] init];

在內存中的表現形式如下:

?

3、什么是引用計數

引用計數是一個簡單而有效的管理對象生命周期的方式。當我們創建一個新的對象的時候,它的引用計數為1,當有一個新的指針指向這個對象時,我們將其引用計數+1,當某個指針不在指向這個對象,我們將其引用計數-1,當對象的引用計數為0是,說明該對象不再被任何指針指向了,我們就可以將對象銷毀,回收內存。如圖所示。

?

?4、MRC手動管理引用計數

a、在MRC中增加引用計數都是需要自己手動釋放的。

對象操作OC中對應的方法引用計數的變化
生成并持有對象alloc/new/copy/mutableCopy等+1
持有對象retain+1
釋放對象release-1
廢棄對象dealloc0

b、四則法則

  • 自己生成的對象,自己持有。
/** 自己生成并持有該對象*/id obj0 = [[NSObeject alloc] init];id obj1 = [NSObeject new];
  • 非自己生成的對象,自己也能持有。
/** 持有非自己生成的對象*/ id obj = [NSArray array]; // 非自己生成的對象,且該對象存在,但自己不持有[obj retain]; // 自己持有對象
  • 不在需要自己持有對象的時候,釋放。
/** 不在需要自己持有的對象的時候,釋放*/ id obj = [[NSObeject alloc] init]; // 此時持有對象[obj release]; // 釋放對象 /** 指向對象的指針仍就被保留在obj這個變量中* 但對象已經釋放,不可訪問*/
  • 非自己持有的對象無需釋放。
/** 非自己持有的對象無法釋放*/ id obj = [NSArray array]; // 非自己生成的對象,且該對象存在,但自己不持有[obj release]; // ~~~此時將運行時crash 或編譯器報error~~~ 非 ARC 下,調用該方法會導致編譯器報 issues。此操作的行為是未定義的,可能會導致運行時 crash 或者其它未知行為

5、ARC自動管理引用計數

ARC其實也是基于引用計數,只是編譯器在編譯時期自動在已有代碼中插入合適的內存管理代碼(包括retain,release,copy,autorelease,autoreleasepool)以及在Runtime做一些優化。

ARC已經處理了大部分的引用計數,還有一小部分的引用計數需要自己管理,這一部分就是底層Core Foundation對象因為不在ARC的管理下,所以需要自己維護這些對象的引用計數。

所有權修飾符:

OC編程中為了處理對象,可將變量類型定義為id類型或各種對象類型。ARC中id類型和對象類型其類型必須附加所有權修飾符。

以下是四種所有權修飾符:

  • __strong
  • __weak
  • __unsafe_unretained
  • __autoreleasing

所有權修飾符和屬性修飾符對應關系如下表:

所有權修飾符屬性修飾符
__unsafe_unretainedassign
__unsafe_unretainedunsafe_unretained
__strongcopy
__strongstrong
__strongretain
__weakweak

a、__strong簡介

__strong表示強引用,對應定義property時用到的是strong。當對象沒有任何一個強引用指向他的時候,他才會被釋放。如果聲明引用時不加修飾符,那么引用將默認是強引用。當需要釋放強引用指向的對象時,需要保證所有指向對象強引用置為nil。_strong修飾符是id類型和對象類型默認的所有權修飾符。

b、__weak簡介

__weak表示弱引用,對應定義property時用的是weak。弱引用不會影響對象的釋放,而當對象被釋放時,所有指向他的弱引用都會自定被置為nil,這樣可以防止野指針。使用__weak修飾的變量,即是使用注冊到autoreleasepool(自動釋放池)中的對象。__weak最常見的一個作用就是用來避免循環引用。

c、__unsafe_unretained簡介

這個修飾符在定義property是對應的是unsafe_unretained。__unsafe_unretained修飾的指針純粹只是指向對象,沒有任何額外的操作,不會去持有對象使得對象retainCount+1。而在指向的對象被釋放時依舊原原本本的指向原來的對象地址,不會被自動置為nil,所以會變成野指針。

d、__autoreleasing簡介

將對象賦值給附有__autoreleasing修飾符的變量等同于MRC時調用對象的autorelease方法。 、6、ARC下的內存管理問題

a、過度使用block之后,無法解決循環引用問題。

b、遇到底層Core Foundation對象,需要自己手工管理他們的引用計數時,顯得一籌莫展。

循環引用問題:

引用計數這種內存管理方式雖然很簡單,但是有一個比較大的瑕疵,就是他不能很好的解決循環引用問題。如下圖所示:

?

對象A和對象B,相互引用了對方作為自己的成員變量,只有當自己銷毀時,才會將成員變量的引用計數-1。因為對象A的銷毀依賴于對象B銷毀,而對象B的銷毀也依賴于對象A的銷毀,這樣就造成了我們稱之為循環引用的問題,這兩個對象即使在外界已經滅有任何指針能夠訪問到他們了,他們也無法被釋放。

不止存在兩對象循環引用的問題,多個對象依次持有對方,形成一個環狀,也可以造成循環引用問題,而且在真實的編程環境中,環越大就越難被發現。如下圖所示:

?

解決循環引用問題,主要有兩種方式:

  • 主動斷開循環引用

我明確知道這里存在循環引用,在合理的位置主動斷開環中的一個引用,使得對象得以回收

  • 使用弱引用

弱引用雖然持有對象,但是并不增加引用計數,這樣就避免了循環引用的產生。在IOS開發中,弱引用通常在delegate模式中使用。舉個例子來說,兩個ViewController A和B,ViewController A需要彈出一個ViewController B,讓用戶輸入一些內容,當用戶輸入完成后,ViewController B需要將內容返回給ViewController A。這個時候,ViewController的delegate成員變量通常是一個弱引用,以避免這兩個ViewController相互引用對方造成循環引用問題,如下圖所示。

?

弱引用的實現原理就是這樣,系統對于每一個弱引用的對象,都維護一個表來記錄他所有的弱引用的指針地址。當一個對象的引用計數為0,系統就通過這張表,找到所有的弱引用指針,繼而把他們都置成nil。

7、Core Foundation 對象的內存管理

底層的Core Foundation對象,在創建時大多以XxxCreateWithXxx這樣的方式創建,例如:

// 創建一個 CFStringRef 對象 CFStringRef str= CFStringCreateWithCString(kCFAllocatorDefault, “hello world", kCFStringEncodingUTF8);// 創建一個 CTFontRef 對象 CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);

對于這些對象的引用計數的修改,要相應的使用 CFRetain 和 CFRelease 方法。如下所示:

// 創建一個 CTFontRef 對象 CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", fontSize, NULL);// 引用計數加 1 CFRetain(fontRef);// 引用計數減 1 CFRelease(fontRef);

對于CFRetain和CFRelease兩個方法,可以與OC對象的retain和release方法等價。所以對于底層Core Foundation對象,我們用手工管理引用計數的辦法就可以。

但是在ARC下,我們有時需要將一個Core Foundation對象轉換成OC對象,需要引入bridge相關的關鍵字。 _bridge:只做類型轉換,不修改相關對象的引用計數,原來的Core Foundation對象在不用時,需要調用CFRelease方法。 _bridge_retained:類型轉換后,將相關對象的引用計數+1,原來的Core Foundation對象在不用時,需要調用CFRelease方法。 _bridge_transfer:類型轉換后,將該對象的引用計數交給ARC管理,Core Foundation對象在不用時,不再需要調用CFRelease方法。

IOS內存管理

?四、參考文檔

strong與copy的區別

IOS屬性

IOS深拷貝和淺拷貝

IOS內存管理

總結

以上是生活随笔為你收集整理的OC语言学习记录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。