淺復(fù)制和深復(fù)制
? ? ? ?關(guān)于淺復(fù)制和深復(fù)制真椿,之前一直都沒有系統(tǒng)的理一遍,今天就來做做總結(jié)歸納乎澄。什么是淺復(fù)制,什么是深復(fù)制测摔,我覺得用一句簡單的話來說淺復(fù)制就是指針復(fù)制置济,深復(fù)制就是內(nèi)容復(fù)制。
? ? 我們先來看一個例子:
? ? ? ? 由示例程序可以看出锋八,不可變字符串只有在使用mutableCopy時才進行的深復(fù)制浙于,使用copy時進行的淺復(fù)制,而可變字符串不管使用copy還是mutableCopy都是深復(fù)制挟纱。其實這個規(guī)律不止對NSString 適用羞酗,對系統(tǒng)的一些其他對象同樣適用,下面我展示了一張簡易的對照表:
? ? ? ? 上面說的都是系統(tǒng)類紊服,那如果使我們自定義類又會是怎么樣呢檀轨?請看下面的例子:
? ? ? 首先聲明一下為什么要實現(xiàn)上述的copyWithZone和mutableCopyWithZone方法胸竞?其實在iOS中并不是所有的對象都支持copy、mutableCopy方法参萄,只有遵守NSCopying協(xié)議的類可以發(fā)送copy消息卫枝,遵守NSMutableCopying協(xié)議的類才可以發(fā)送mutableCopy消息,否則就會崩潰讹挎。所以當我們想對自定義的類實現(xiàn)復(fù)制時校赤,就需要遵守這些協(xié)議寫上這些方法。在上例中兩種方式都是深復(fù)制筒溃,原因也很簡單马篮,因為它們都創(chuàng)建了新的對象。
? ? ? ? 到這里了我們不妨再想想怜奖,那既然自定義的對象是深復(fù)制积蔚,那對象的屬性呢,是深復(fù)制還是淺復(fù)制烦周?
? ? ? ? 由示例程序可以看到尽爆,Address類的street屬性打印為456,表明他是深復(fù)制读慎,其實要想明白這個問題很簡單漱贱,他的關(guān)鍵在于這里我street的屬性修飾符是copy,相當于對可變字符串street進行了深復(fù)制夭委,生成了一個新的對象幅狮,然后賦值給了Address類的屬性。如果這里換成strong株灸,結(jié)果就會為456789崇摄,因為strong會持有原來的對象,是淺復(fù)制慌烧。
? ? ? ? 事情到這里了好像一切明朗起來了逐抑,但是還有一個問題,請看下面這個例子:
? ? ? ? 這個例子中屹蚊,dataArray和dataArray2是進行了深復(fù)制厕氨,由最后打印的內(nèi)存地址可以看出,但是為什么改變了dataArray2的元素dataArray中的元素也跟著變了呢汹粤?當我們在用mutableCopy方法復(fù)制元素時命斧,在內(nèi)存中為新的數(shù)組分配了空間,并且將單個元素復(fù)制到新數(shù)組中嘱兼。然而將原始數(shù)組中的每一個元素復(fù)制到新位置意味著:緊將一個數(shù)組元素復(fù)制到另一個數(shù)組元素国葬。這樣做的最終結(jié)果,就是這兩個數(shù)組中的元素都指向內(nèi)存中的同一個字符串。那么我們到底要怎么樣才能為數(shù)組中的每一個元素創(chuàng)建完全不同的副本汇四,而不僅是職責(zé)一些對象的引用副本呢接奈,這就需要用到我們接下來要介紹的歸檔技術(shù)。
歸檔
? ? ? ? 在Objective-C中船殉,歸檔是一個過程鲫趁,即用某種格式來保存一個或多個對象,以便以后還原這些對象利虫。下面我們來介紹一下歸檔的集中方法挨厚。
使用XML屬性列表進行歸檔
如果你的對象是NSString,NSDictionary,NSArray,NSData,NSNumber類型,你可以使用這些類中實現(xiàn)的writeToFile:atomically:方法將數(shù)據(jù)寫到文件中糠惫,在寫出某個字典或數(shù)組的情況下疫剃,該方法可以使用XML屬性列表的格式寫出數(shù)據(jù)。下面是示例程序:
? ? ? ?atomically參數(shù)設(shè)置為yes硼讽,表示希望首先將字典寫入臨時備份文件中巢价,并且一旦成功,將把最終數(shù)據(jù)轉(zhuǎn)移到名為test的指定文件中固阁,這是一種安全措施壤躲,它保護文件在一些情況下(如系統(tǒng)在執(zhí)行操作過程中崩潰時)免受破壞。
使用NSKeyedArchiver歸檔
? ? ?若要將各種類型的對象存儲到文件中备燃,而且不僅僅是字符串碉克,數(shù)組和字典類型,有一種更靈活的辦法并齐,就是利用NSKeyedArchiver類創(chuàng)建帶鍵的檔案來完成漏麦。
1.基本的Objective-C歸檔
2.歸檔自定義類型
? ? ? ?要歸檔自定義的類型,我們必須告訴系統(tǒng)要如何歸檔我們的對象况褪,以及如何解歸檔它們撕贞。這就要求我們必須實現(xiàn)NSCoding協(xié)議,在類中添加encodeWithCoder:方法和initWithCoder:方法實現(xiàn)测垛。下面是示例程序:
使用NSData創(chuàng)建自定義檔案
? ? 有時候可能不想和前面一樣捏膨,可能想收集一些或所有的對象,并將其存儲到單個檔案文件中赐纱,在Objective-C中脊奋,通過使用名為NSData的通用數(shù)據(jù)流對象類,可以實現(xiàn)上述功能疙描。示例程序如下:
使用歸檔程序深復(fù)制對象
? ? ? ? 最后一點內(nèi)容,我們來介紹一下如何使用歸檔來實現(xiàn)前面遺留的深復(fù)制問題讶隐。示例代碼如下:
? ? ? ? 這個輸出結(jié)果驗證了更改了dataArray2但并沒有影響dataArray的元素起胰,實現(xiàn)了數(shù)組的深復(fù)制。