關于OC修飾詞的反思

代碼寫久了,對于一些基礎的東西記憶反而慢慢變得模糊
一些已經習以為常的東西,知道如何去用但是表達不清晰
有時候自己說得清楚,被面試官一繞就要反應一下,
不如自己靜下心來總結總結

Objective-C 是OOP(面向對象)的語言
有面向對象就有 類和對象
有類就有屬性 (實例變量暫且不提)
而OC的屬性(property)是通過用@property定義的公有或私有的方法

例如工程中Appdelegate.h中 系統(tǒng)默認生成
@property (strong, nonatomic) UIWindow *window;

===============
修飾詞
上述例子中()內的部分叫修飾詞,用于表明對象的屬性。

OC中的屬性property按照其功能分為以下三種類型:
線程安全:atomic/nonatomic
內存管理:assign/strong/weak/copy
讀寫權限:readonly/readwrite

Objective-C 中,
基本數據類型 默認關鍵字是atomic, readwrite, assign;
普通屬性(帶*的) 默認關鍵字是atomic, readwrite, strong。

//atomatic nonatomic區(qū)別和理解

atomic和nonatomic區(qū)別用來決定編譯器生成的getter和setter是否為原子操作。
atomic提供多線程安全,是描述該變量是否支持多線程的同步訪問,如果選擇了atomic 那么就是說,系統(tǒng)會自動的創(chuàng)建lock鎖,鎖定變量。
nonatomic禁止多線程,變量保護,提高性能。
主要的區(qū)別在于多線程操作一個對象時,用nonatomic的話,getter可能會取到只更改了其中一個變量時候的狀態(tài),這樣取到的東西會有問題,就是不完整的。而atomic可以保證在多線程環(huán)境下,解析的訪問器提供一個對屬性的安全訪問,但是性能會比較低。
*如果要保證絕對的線程安全,可通過加鎖的方式,例如@synchronized.

//ARC下的內存屬性

strong: 表示指向并擁有該對象。其修飾的對象引用計數會增加1。該對象只要引用計數不為0則不會被銷毀。當然強行將其設為nil可以銷毀它。
weak: 表示指向但不擁有該對象。其修飾的對象引用計數不會增加。無需手動設置,該對象會自行在內存中銷毀。
assign: 主要用于修飾基本數據類型,如NSInteger和CGFloat,這些數值主要存在于棧上。表示對屬性只進行簡單的賦值操作,不更改所賦的新值的引用計數,也不改變舊值的引用計數,常用于標量類型,如NSInteger,NSUInteger,CGFloat,NSTimeInterval等。assign修飾的對象被釋放后,指針的地址依然存在,造成野指針,在堆上容易造成崩潰。而棧上的內存系統(tǒng)會自動處理,不會造成野指針。

//MRC下的內存屬性

retain:OC對象類型
copy:NSString、Block等類型
assign:非OC對象類型, 基本數據類型
(兩個對象相互引用的時候,一端用retain, 一端用assign???。。。此處存疑。。。)

//copy和strong的區(qū)別
copy與strong類似。不同之處是strong的復制是多個指針指向同一個地址,而copy的復制每次會在內存中拷貝一份對象,指針指向不同地址。copy一般用在修飾有可變對應類型的不可變對象上,如NSString, NSArray, NSDictionary。

//strong和weak的區(qū)別
想起來第一次看書的時候有個例子講,對象是狗(感覺怪怪的。。),引用就是繩子。強引用就是繩子牽著狗,弱引用就是目光看著狗。有多少強引用就有多少條繩子,所有繩子都脫落,狗才會跑(得到釋放),而弱引用沒有繩子綁著狗,當這個狗其他的強引用放掉了就跑了,再多目光都沒有用,只能得到一個nil。所以,只要最后一個strong型指針不再指向對象,那么對象就會被釋放,同時所有的weak型指針都將會被清除。

//UIView應該用strong還是weak修飾
都存在。

使用 sb 或者 xib 給控件拖線的時候,拖出來的線屬性都是用 weak 修飾,原因是由于在向 xib 或者 sb 里面添加控件的時候,添加的子視圖是添加到了根視圖 View 上面, 而 控制器 Controller 對其根視圖 View 默認是強引用的,當我們的子控件添加到 view 上面的時候, [self.view addSubView: xxx]這個方法會對添加的控件進行強引用,如果在用 strong 對添加的子控件進行修飾的話,相當于有兩條強指針對子控件進行強引用, 為了避免這種情況,所以用 weak 修飾。

在純手碼實現界面布局時,如果通過懶加載處理界面控件,需要使用strong強指針。假如你是弱引用,在removeFromSuperview的時候將自動引用計數-1,等你第二次addSubview的時候,這個view可能已經被釋放了,就會造成崩潰。

在ARC中,對象釋放的最終根據還是根據引用計數為0時去釋放。而weak與strong的根本區(qū)別是在set方法中,weak的set方法和strong的set方法都是釋放舊值保留新值,但是weak的set方法會對其autorelease,即延遲release一次,而strong的set方法也是釋放舊值保留新值,但是其不會延遲release。最終效果是strong會+1,weak不會+1。

//關于copy的深拷貝,淺拷貝,以及相關引用計數
淺拷貝:拷貝地址,僅僅是指向被復制的內存地址,如果原地址中對象被改變了,那么淺復制出來的對象也會相應改變。
深拷貝Deep Copy:在計算機中開辟了一塊新的內存地址用于存放復制的對象。

Copy在Objetive-C中的實現方式。如果要調用一個對象的copy方法,這個對象必須遵循NSCopying的協(xié)議。這個協(xié)議中規(guī)定了一個方法:- (id)copyWithZone:(NSZone *)zone;我們就是通過實現這個方法給對象提供拷貝的功能。對于很多現有類,如NSString,NSDictionary...這個方法已經實現。假設我們現在自定義了一個類,需要為這個類提供拷貝的功能,就需要自己來動手寫CopyWithZone的方法。

實際使用中區(qū)分深拷貝和淺拷貝有個技巧,[string copy]就是淺拷貝,[string mutableCopy]就是深拷貝,前者返回的NSString在runtime下“真身”是__NSCFConstantString,而NSMutableString的“真身”是__NSCFString,然后我們就能很清楚的看到,只要是copy得到的值就是不可變類型,而mutablecopy得到的是可變類型。

總結

可變的用strong修飾,不可變的用copy修飾
假如可變的用copy修飾了,就變不可變了,set的時候會崩潰
假如不可變的用strong修飾了,指針指向的地址值修改了依然會被修改,不安全

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容