天天看點

copy和strong的差別及使用不當引起的crash

copy屬性用在需要深拷貝的地方,如:block屬性。它會造成記憶體增加,使用不當會造成拷貝異常而崩潰。strong屬性用在需要淺拷貝,隻要指向它的所有對象不都被釋放,用它聲明的屬性對象就不會被釋放。如:對象屬性。

1.資料源為可變字元串而言,使用copy申明屬性,會開辟一塊新的記憶體空間存放值,源資料不論怎麼變化,都不會影響copy屬性中的值,屬于深拷貝;使用strong申明屬性,不會開辟新的記憶體空間,隻會引用源資料記憶體位址,是以源資料改變,則strong屬性也會改變,屬于淺拷貝。

在響應式程式設計的開發模式下,為了保持資料的一緻性,通常對NSMutableString等可變類型屬性仍舊使用strong聲明。響應式程式設計的資料處理過程式,從服務接收到消息(加密的json字元串),經過app網關(網絡請求元件)進行解密,消息統一,轉換為字典;然後經過view-model進行資料預先處理轉換具體實體類;然後傳遞到view層進行資料展示。在消息傳遞過程中可能對原始資料進行修改,為了保證資料的唯一性,是以最好用strong聲明。

當然在mvc建構時通常資料解析是在UIViewController直接解析的,是以不存在資料傳輸過程,可能使用copy聲明更合适。

源對象為不可變字元串而言,不論使用copy還是strong屬性,所對應的值是不發生變化,strong和copy并沒有開辟新的記憶體,即并不是深拷貝。此時,使用copy或是strong,并沒有對資料産生影響。

2.源對象為不可變字元串而言,不論使用copy還是strong屬性,所對應的值是不發生變化,strong和copy并沒有開辟新的記憶體,即并不是深拷貝。此時,使用copy或是strong,并沒有對資料産生影響。

3.屬性為可變數組、可變字典copy申明的可變資料,初始化或複值之後,變成不可變數組,對數組執行增,删會跑出錯誤。這是因為copy屬性修飾後,在初始化或指派時,會先執行copy操作,然後指派。

由于一個對象的block可以在多個對象中注冊,是以要用深拷貝,就是要用copy聲明。不能用strong聲明。當然這個block隻在最後一個注冊的對象中生效。

下面是使用copy聲明對象,引起無法識别對象崩潰的具體例子。崩潰的原因是:copy聲明的對象變量隻能對基本對象或block進行深拷貝,若是自定義對象不實作NSCoding協定(序列和反序列化)并聲明為copy類型就會發生這種不測!

copy和strong的差別及使用不當引起的crash
copy和strong的差別及使用不當引起的crash

可以看到self.alvEntity有記憶體位址,但是它的ai屬性為nil,結果由于它是用copy聲明的,結果在執行

self.alvEntity.ai = ai;

指令進行深拷貝時崩潰了。解決方案很簡單:

@property (nonatomic, strong) AddressInfo *ai;

是以要了解copy和strong的差別,合理使用。簡言之:block屬性全用copy,其它全用strong。當然你有特别要求,對可變字元串資料源,關注跟蹤整個資料的變化過程,不關注資料一緻性,不關注記憶體的那點增加,那麼你可以使用copy聲明可變字元串。

繼續閱讀