readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak屬性的作用分別是什么。
關鍵字注釋
readwrite此標記說明屬性會被當成讀寫的,這也是默認屬性。
readonly此標記說明屬性只可以讀,也就是不能設置,可以獲取。
assign不會使引用計數(shù)加1,也就是直接賦值。
retain會使引用計數(shù)加1。
copy建立一個索引計數(shù)為1的對象,在賦值時使用傳入值的一份拷貝。
nonatomic非原子性訪問,多線程并發(fā)訪問會提高性能。
atomic原子性訪問。
strong打開ARC時才會使用,相當于retain。
weak打開ARC時才會使用,相當于assign,可以把對應的指針變量置為nil。
為什么代理要用weak?
首先明白什么情況使用 weak 關鍵字?
在 ARC 中,在有可能出現(xiàn)循環(huán)引用的時候,往往要通過讓其中一端使用 weak 來解決
delegate 代理屬性,代理屬性也可使用
assign自身已經(jīng)對它進行一次強引用,沒有必要再強引用一次,此時也會使用 weak
自定義IBOutlet 控件屬性一般也使用weak;當然,也可以使用 strong,但是建議使用 weak
weak 在屬性所指的對象遭到摧毀時,系統(tǒng)會將 weak 修飾的屬性對象的指針指向 nil,在 OC 給 nil 發(fā)消息是不會有什么問題的;如果使用 assign 策略在屬性所指的對象遭到摧毀時,屬性對象指針還指向原來的對象,由于對象已經(jīng)被銷毀,這時候就產(chǎn)生了野指針,如果這時候在給此對象發(fā)送消息,很容造成程序奔潰assigin 可以用于修飾非 OC 對象,而 weak 必須用于 OC 對象。
block和代理的區(qū)別?
block 和 delegate 都可以通知外面。block 更輕型,使用更簡單,能夠直接訪問上下文,這樣類中不需要存儲臨時數(shù)據(jù),使用 block 的代碼通常會在同一個地方,這樣讀代碼也連貫。delegate 更重一些,需要實現(xiàn)接口,它的方法分離開來,很多時候需要存儲一些臨時數(shù)據(jù),另外相關的代碼會被分離到各處,沒有 block 好讀。
應該優(yōu)先使用 block。而有兩個情況可以考慮 delegate。
1. 有多個相關方法。假如每個方法都設置一個 block, 這樣會更麻煩。而 delegate 讓多個方法分成一組,只需要設置一次,就可以多次回調(diào)。當多于 3 個方法時就應該優(yōu)先采用 delegate。
2. 為了避免循環(huán)引用,也可以使用 delegate。使用 block 時稍微不注意就形成循環(huán)引用,導致對象釋放不了。這種循環(huán)引用,一旦出現(xiàn)就比較難檢查出來。而 delegate 的方法是分離開的,并不會引用上下文,因此會更安全些。
將 block 簡單分類,有三種情形。
* 臨時性的,只用在棧當中,不會存儲起來。比如數(shù)組的 foreach 遍歷,這個遍歷用到的 block 是臨時的,不會存儲起來。
* 需要存儲起來,但只會調(diào)用一次,或者有一個完成時期。比如一個 UIView 的動畫,動畫完成之后,需要使用 block 通知外面,一旦調(diào)用 block 之后,這個 block 就可以刪掉。
* 需要存儲起來,可能會調(diào)用多次。比如按鈕的點擊事件,假如采用 block 實現(xiàn),這種 block 就需要長期存儲,并且會調(diào)用多次。調(diào)用之后,block 也不可以刪除,可能還有下一次按鈕的點擊。
對于臨時性的,只在棧中使用的 block, 沒有循環(huán)引用問題,block 會自動釋放。而只調(diào)用一次的 block,需要看內(nèi)部的實現(xiàn),正確的實現(xiàn)應該是 block 調(diào)用之后,馬上賦值為空,這樣 block 也會釋放,同樣不會循環(huán)引用。而多次調(diào)用時,block 需要長期存儲,就很容易出現(xiàn)循環(huán)引用問題。
Cocoa 中的 API 設計也是這樣的,臨時性的,只會調(diào)用一次的,采用 block。而多次調(diào)用的,并不會使用 block。比如按鈕事件,就使用 target-action,有些庫將按鈕事件從 target-action 封裝成 block 接口, 反而容易出問題。