iOS copy/strong作為修飾詞對屬性值的影響

最近開發(fā)遇到的一個問題,就是copy和strong作為屬性的修飾詞的區(qū)別,看了好多文章,沒有幾篇能夠講的很明白的,所以自己就梳理了一編。

第一步:

定義個不可變的對象,分別用copy和strong來作為修飾詞

@property(nonatomic,strong) NSArray *strongArr;

@property (nonatomic,copy) NSArray *copyarr;

下面就來看看他們的區(qū)別

首先我們定義一個可變的對象,先來看賦值操作

NSMutableArray *arr = [NSMutableArray new];

[arr addObject:@1];

_strongArr = arr;

_copyarr = arr;

[arr addObject:@2];

打印結果:

?arr內存地址及指針指向:0x600002ebf030,0x7ffee4472158,

?_strongArr:內存地址及指針指向:0x600002ebf030,0x7fcad6405080,

_copyarr:內存地址及指針指向:0x600002ebf030,0x7fcad6405088,

從內存地址來看無論是copy還是strong修飾的對象同屬同一內存地址,所以對arr的值進行修改他們都會改變即使是把arr賦給不可變的對象后;因為指針不同但是指向的內存地址都是一樣的;

再來想一個問題如果把_strongArr和_copyarr換成self.xxx的形式結果還是一樣嗎?

?self.strongArr= arr;? ? ? ? self.copyarr= arr;? ? ? [arr addObject:@2];

打印結果:

?arr內存地址及指針指向:0x6000022526a0,0x7ffee006b158,

arr數組里面的元素(?1,? ? 2)

?self.strongArr:內存地址及指針指向:0x6000022526a0,0x7f85a5f053d0,

strongArr數組里面的元素(?1,?2)

?self.copyarr:內存地址及指針指向:0x600002e2bb00,0x7f85a5f053d8,

copyarr數組里面的元素(?1)

可以看到從打印出來的數據可以看到對self.strongArr和 self.copyarr賦值后 ,再對原始數組arr進行操作后,copy修飾的屬性這次內存地址發(fā)生了變化,是個新的內存地址,所以數組里面的參數沒有變化,為什么呢,后面講解。

再看看可變數組:

@property(nonatomic,strong) NSMutableArray *strongMutableArr;

@property (nonatomic,copy) NSMutableArray *copymutablearr;

再看看copy和strong修飾的可變對象賦值操作

?_strongMutableArr= arr;

? _copymutablearr = arr;

[arr addObject:@2];

打印結果:

?arr內存地址及指針指向:0x600001d84a50,0x7ffee8116158,

arr數組里面的元素(

? ? 1,

? ? 2

)

strongMutableArr:內存地址及指針指向:0x600001d84a50,0x7fd81bd03ac0,_

strongMutableArr數組里面的元素(

? ? 1,

? ? 2

)

_copymutablearr:內存地址及指針指向:0x600001d84a50,0x7fd81bd03ac8,

copymutablearr數組里面的元素(

? ? 1,

? ? 2

)

和不可變的對象執(zhí)行結果是一樣的,都是在同一個內存地址,那么問題來了,我可以對copymutablearr這個數組進行操作嗎?

來試一下:

?[_copymutablearr addObject:@"這是copy修飾的可變數組添加的元素"];

打印結果:

arr數組里面的元素(

? ? 1,

? ? 2,

? ? "\U8fd9\U662fcopy\U4fee\U9970\U7684\U53ef\U53d8\U6570\U7ec4\U6dfb\U52a0\U7684\U5143\U7d20"

)

strongMutableArr數組里面的元素(

? ? 1,

? ? 2,

? ? "\U8fd9\U662fcopy\U4fee\U9970\U7684\U53ef\U53d8\U6570\U7ec4\U6dfb\U52a0\U7684\U5143\U7d20"

)

copymutablearr數組里面的元素(

? ? 1,

? ? 2,

? ? "\U8fd9\U662fcopy\U4fee\U9970\U7684\U53ef\U53d8\U6570\U7ec4\U6dfb\U52a0\U7684\U5143\U7d20"

)

可見這3個數組只要有個一改變,都會發(fā)生改變,因為他們是在同一內存地址。

self.xxx=arr,打印結果和不可變的數組結果是一樣的,self.XXX也是從新生成了一個新的內存地址;

[self.copymutablearr addObject:@"這是copy修飾的可變數組添加的元素"];?

這時候對copy數組進行操作會崩潰掉,

問題來了為什么copy修飾的_xxx=arr就可以對_xxx進行操作,而self.xxx=arr對self.xxx進行操作就會崩潰呢;

看下面的數據


self.xxx=arr
_xxx=arr

從類型上可以看出用copy修飾的,self.xxx=arr的時候可變數組變成了nssingleobjetarryi類型,他是說明只有一個元素,也不是可變數組的類型,如果沒有元素就是_NSArray0,而可變數組是_NSArrayM類型,無論有多少元素可變數組應該是_NSArayM標記;而且崩潰日志也提示沒有找到addObject:這個方法,說明copy修飾時用self.xxx進行被賦值的話就變成了不可變數組,前提是self.xxx才會有影響;

再來看兩張圖


self.xxx= arr(可變數組)
_xxx=arr(可變數組)

當不可變數組被賦值的時候,self.xxx=arr,用strong和copy修飾時 類型是有區(qū)別的,而_xxx=arr,_xxx的類型是沒有區(qū)別的,原數組是什么類型被賦值的類型是源類型;


從上面四張圖可以得出結論;

strong修飾的無論是可變的還是不可變的對象,無論是self.xxx還是_xxx,被賦值的對象類型都指向了賦值的對象類型arr,也就是說他們都是在同一內存地址下面,有一個動的其它的也會動;

copy修飾時_xxx無論是可變的還是不可變的,效果和strong修飾的是一樣的,都是在同一個內存地址,唯一不一樣的就是使用self.xxx時,會開辟新的內存地址;

注:copy修飾時,_xxx=arr時是可以對_xxx進行操作的,但是self.xxx=arr就不能對self.xxx進行操作了,應為self.xxx變成了不可變的了;


為什么self.xxx用copy修飾進行賦值操作的時候會開辟一個新的內存地址呢?

因為self.xxx進行賦值操作的話會走setter方法,而用copy修飾setter方法里面會進行一次深copy 操作,所以self.語法會從新分配新的內存地址;

所以說平時開發(fā)過程中屬性修飾詞用copy的時候一定要注意self.語法會重新開辟新的線程,沒有strong修飾更加便捷,開內存就意味著消耗,慎用!

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容