iOS 之深淺拷貝 Copy

淺拷貝卧蜓、深拷貝

Copy的作用

  • 在OC中帐要,copy 是利用一個源對象產(chǎn)生一個副本對象,本質(zhì)就是當(dāng)修改源對象的屬性和行為弥奸,不會影響副本對象榨惠,同樣,當(dāng)修改副本對象的屬性和行為,不會影響源對象赠橙。

Copy 的使用

  • 注意: 使用之前必須要遵守 NSCopying 協(xié)議耽装,實現(xiàn) copyWithZone: 方法
其中有兩點需要注意:

1、Foundation類已經(jīng)遵守了<NSCopying>和 <NSMutableCopying>協(xié)議,即實現(xiàn)了copy和mutableCopy方法,因此Foundation對象可以使用這些方法創(chuàng)建對象的副本或可變副本期揪,例如: NSString 掉奄、 NSDictionary 、NSArray 凤薛、 NSMutableArr ...

2姓建、在iOS中并不是所有的對象都支持copy,mutableCopy缤苫,遵守NSCopying 協(xié)議的類可以發(fā)送copy消息速兔,遵守NSMutableCopying 協(xié)議的類才可以發(fā)送mutableCopy消息。假如發(fā)送了一個沒有遵守上訴兩協(xié)議而發(fā)送 copy或者 mutableCopy,那么就會發(fā)生異常榨馁。如果想自定義一下copy 那么就必須遵守 NSCopying,并且實現(xiàn) copyWithZone: 方法憨栽,如果想自定義一下mutableCopy 那么就必須遵守NSMutableCopying,并且實現(xiàn) mutableCopyWithZone: 方法, 總之想要 Copy 或是mutableCopy 必須要實現(xiàn) copyWithZone: 或是 mutableCopyWithZone: 方法 這兩個方法翼虫,協(xié)議不簽訂也沒有問題屑柔,只不過不簽訂協(xié)議沒有協(xié)議方法的代碼提示.

例如: 自定義一個 Person 類,當(dāng)操作 copy 時珍剑,如果沒有實現(xiàn) NSCopying 協(xié)議掸宛,那么會出現(xiàn)錯誤。

    Person *p1 = [[Person alloc]init];
    Person *p2 = [p1 copy];
    NSLog(@"P1 為:%@  P2 為: %@", p1, p2);

自定義類招拙,沒有實現(xiàn) copy 的協(xié)議方法報錯
實現(xiàn)協(xié)議方法,輸出 P1 P2 對象地址
-(id)copyWithZone:(NSZone *)zone
{
    Person *per = [[Person allocWithZone:zone]init];
    return per;
}
查看對象地址唧瘾,地址不一樣

深淺拷貝對比圖

源對象類型 拷貝方法 副本對象類型 是否產(chǎn)生新對象 拷貝類型
NS* copy NS* NO 淺拷貝(指針拷貝
NS* MutableCopy NSMutable* YES 深拷貝(內(nèi)容拷貝)
NSMutable* copy NS* YES 深拷貝(內(nèi)容拷貝)
NSMutable* MutableCopy NSMutable* YES 深拷貝(內(nèi)容拷貝)
自定義對象:

自定義對象不存在可變和不可變對象,所以均為深拷貝

深拷貝 淺拷貝

通過打印上述 P1 P2 對象别凤,我們發(fā)現(xiàn)饰序,內(nèi)存地址是不一樣的(深拷貝),這里我們引入深拷貝和淺拷貝的概念规哪。

淺拷貝

"淺拷貝可以簡單的理解為把對象的引用復(fù)制求豫,或者說對象的指針.指針賦值,使兩個指針指向相同的一塊內(nèi)存空間诉稍,操作不安全蝠嘉。“

深拷貝

”深拷貝拷貝當(dāng)前指針指向的對象杯巨,系統(tǒng)會隨機給拷貝的對象重新分配一塊內(nèi)存蚤告,深拷貝以后,兩份對象的內(nèi)存地址不一樣服爷,指針指向也不一樣杜恰。深拷貝會把當(dāng)前容器中的對象重新拷貝一份放到另一個容器中获诈,拷貝后的指針指向新的容器。不僅拷貝了對象還把指針頁拷貝了”

只有從不可變對象copy到不可變對象的時候才是淺拷貝箫章,其他的都是深拷貝

總結(jié)

1烙荷、對不可變的對象進行mutableCopy操作,是進行了一次深拷貝,返回的對象是可變的對象檬寂。

2终抽、對不可變的對象進行copy操作,進行了一次淺拷貝桶至,返回一個不可變的對象昼伴。

3、對可變得對象進行copy镣屹,進行了深拷貝圃郊,產(chǎn)生了不可變的對象副本。

4女蜈、對可變的對象進行了一次mutableCopy持舆,是進行了一次深拷貝, 返回的對象是一個可變的對象伪窖。

5逸寓、想要讓自定義的對象支持copy和mutableCopy那么就要對應(yīng)實現(xiàn)NSCopying協(xié)議,和NSMutableCopying協(xié)議覆山。

非容器類對象的copy和mutableCopy,以 NSString 為例

    NSString *String = @"字符串";
    self.aNewStr = [String copy];
    self.twoNewStr =[String mutableCopy];
    
    NSLog(@"1*******%p", String);
    NSLog(@"2*******%p", _aNewStr);
    NSLog(@"2*******%p", _twoNewStr);
結(jié)果輸出

2016-06-16 22:54:01.397 oc深淺拷貝[10541:843917] 1*******0x1099bd078
2016-06-16 22:54:01.397 oc深淺拷貝[10541:843917] 2*******0x1099bd078
2016-06-16 22:54:01.398 oc深淺拷貝[10541:843917] 2*******0x7fd959f1d820

通過打印結(jié)果我們可以看出:

  • 通過 Copy 的字符串竹伸,不會產(chǎn)生新對象和String的內(nèi)存地址一樣,這里 copy 為淺拷貝(指針拷貝)
  • 通過 mutableCopy 的字符串簇宽,產(chǎn)生的 twoNewStr 和原始的字符串 String 地址不一樣勋篓,這里產(chǎn)生了新的對象,為深拷貝(內(nèi)容拷貝)

@property 聲明中用 copy 修飾 NSString魏割、NSArray譬嚣、NSDictionary

因為父類指針可以指向子類對象,使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.
如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性.

copy 此特質(zhì)所表達的所屬關(guān)系與 strong 類似。然而設(shè)置方法并不保留新值钞它,而是將其“拷貝” (copy)孤荣。 當(dāng)屬性類型為 NSString 時,經(jīng)常用此特質(zhì)來保護其封裝性须揣,因為傳遞給設(shè)置方法的新值有可能指向一個 NSMutableString 類的實例。這個類是 NSString 的子類钱豁,表示一種可修改其值的字符串耻卡,此時若是不拷貝字符串,那么設(shè)置完屬性之后牲尺,字符串的值就可能會在對象不知情的情況下遭人更改卵酪。所以幌蚊,這時就要拷貝一份“不可變” (immutable)的字符串,確保對象中的字符串值不會無意間變動溃卡。只要實現(xiàn)屬性所用的對象是“可變的” (mutable)溢豆,就應(yīng)該在設(shè)置新屬性值時拷貝一份。

NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];

查看內(nèi)存瘸羡,會發(fā)現(xiàn) string漩仙、stringCopy 內(nèi)存地址都不一樣,說明此時都是做內(nèi)容拷貝犹赖、深拷貝队他。即使你進行如下操作:

[string appendString:@"origion!"]

stringCopy 的值也不會因此改變,但是如果不使用 copy峻村,stringCopy 的值就會被改變麸折。 集合類對象以此類推。 所以粘昨,

用 @property 聲明 NSString垢啼、NSArray、NSDictionary 經(jīng)常使用 copy 關(guān)鍵字张肾,是因為他們有對應(yīng)的可變類型:NSMutableString芭析、NSMutableArray、NSMutableDictionary捌浩,他們之間可能進行賦值操作放刨,為確保對象中的字符串值不會無意間變動,應(yīng)該在設(shè)置新屬性值時拷貝一份尸饺。

retain 和 copy 的區(qū)別

 1进统、retain是對當(dāng)前對象增加了一個指針指向,使對象的引用計數(shù)器加1浪听, 是進行了一次安全的淺拷貝操作螟碎。
 2、copy是對當(dāng)前對象進行了一次拷貝迹栓,重新拷貝了當(dāng)前對象掉分,當(dāng)使用的時候減少了對當(dāng)前對象的依賴


當(dāng)產(chǎn)生子類時,copyWithZone: 方法需要注意的點

如果你的類產(chǎn)生了子類,那么copyWithZone:方法也將被繼承克伊。

Student *stu = [[Student allocWithZone: zone] init];

該方法應(yīng)該改為:

Student *stu = [[[self class] allocWithZone: zone]init];

如果編寫一個類的copyWithZone:方法酥郭,那么子類的方法應(yīng)該先調(diào)用父類的copy方法以復(fù)制繼承來的copy實例變量.

//LIMING 繼承了 Student 在 copy 方法中,要先調(diào)用父類的 copy 方法愿吹, super
LIMING *copy = [super copyWithZone:zone];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末不从,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子犁跪,更是在濱河造成了極大的恐慌椿息,老刑警劉巖歹袁,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異寝优,居然都是意外死亡条舔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門乏矾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孟抗,“玉大人,你說我怎么就攤上這事妻熊】淝常” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵扔役,是天一觀的道長帆喇。 經(jīng)常有香客問我,道長亿胸,這世上最難降的妖魔是什么坯钦? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮侈玄,結(jié)果婚禮上婉刀,老公的妹妹穿的比我還像新娘。我一直安慰自己序仙,他們只是感情好突颊,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潘悼,像睡著了一般律秃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上治唤,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天棒动,我揣著相機與錄音,去河邊找鬼宾添。 笑死船惨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缕陕。 我是一名探鬼主播粱锐,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扛邑!你這毒婦竟也來了怜浅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鹿榜,失蹤者是張志新(化名)和其女友劉穎海雪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體舱殿,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡奥裸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沪袭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湾宙。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖冈绊,靈堂內(nèi)的尸體忽然破棺而出侠鳄,到底是詐尸還是另有隱情,我是刑警寧澤死宣,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布伟恶,位于F島的核電站,受9級特大地震影響毅该,放射性物質(zhì)發(fā)生泄漏博秫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一眶掌、第九天 我趴在偏房一處隱蔽的房頂上張望挡育。 院中可真熱鬧,春花似錦朴爬、人聲如沸即寒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽母赵。三九已至,卻和暖如春蚣常,著一層夾襖步出監(jiān)牢的瞬間市咽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工抵蚊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留施绎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓贞绳,卻偏偏與公主長得像谷醉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子冈闭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文為轉(zhuǎn)載: 作者:zyydeveloper 鏈接:http://www.reibang.com/p/5f776a...
    Buddha_like閱讀 877評論 0 2
  • 一矛绘、從面向?qū)ο蟮絆bjective-C概覽copy 1、面向?qū)ο螅?In object-oriented prog...
    adrian920閱讀 754評論 0 3
  • 1刃永、對象拷貝有兩種方式:淺復(fù)制和深復(fù)制货矮。顧名思義,淺復(fù)制斯够,并不拷貝對象本身囚玫,僅僅是拷貝指向?qū)ο蟮闹羔槪簧顝?fù)制是直接...
    滴答大閱讀 772評論 0 2
  • 如果說搖滾是奔放硬朗的身子骨读规,那民謠一定是其中柔軟細致的靈魂抓督。 聽歌很少,也都相對主流一些束亏。遇上喜歡的铃在,必然循環(huán)百...
    一尾羊閱讀 335評論 0 0
  • 有一句話現(xiàn)在最適合不過,生活越接近平淡枪汪,內(nèi)心越接近絢爛涌穆。 大學(xué)畢業(yè)后,生活平淡雀久,但是滿足宿稀。 年輕的人,心懷都比天高...
    靈翼之光閱讀 179評論 0 0