iOS NSString copy 與 strong 誤區(qū)指引

今天對 NSString copystrong屬性進行一次在ARC模式下的詳解,與MRC模式下,主要是retain 引用計數(shù)的問題 (+1,不+1,加多少個1,跟你沒有半毛錢的關(guān)系,??此處廢話,忽略)。
copy屬性的意思就是復制一份給自己,strong屬性就是強引用。很好理解,我們先來看看效果。

@property (nonatomic,copy) NSString *c_String;

@property (nonatomic,strong) NSString *s_String;

定義一個可變的字符串tempString,分別對c_String、s_String進行賦值,然后對它們的值、變量的內(nèi)存地址、變量的地址進行打印。

    NSMutableString *tempString = [NSMutableString stringWithFormat:@"original"];
    self.s_String = tempString;
    self.c_String = tempString;
    // before change
    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);
    
    [tempString appendString:@"change"];
    // after change
    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);

下面是打印結(jié)果??

2017-09-11 22:42:16.981 Refreshing_demo1[2043:102101] tempString:original strongString:original copyString:original
2017-09-11 22:42:16.982 Refreshing_demo1[2043:102101] tempString:0x6080000756c0 strongString:0x6080000756c0 copyString:0xa000c505a04b2028
2017-09-11 22:42:16.982 Refreshing_demo1[2043:102101] tempString:0x7fff58006738 strongString:0x7fc6d4d0d0b0 copyString:0x7fc6d4d0d0a8

2017-09-11 22:42:16.982 Refreshing_demo1[2043:102101] tempString:originalchange strongString:originalchange copyString:original
2017-09-11 22:42:16.982 Refreshing_demo1[2043:102101] tempString:0x6080000756c0 strongString:0x6080000756c0 copyString:0xa000c505a04b2028
2017-09-11 22:42:16.983 Refreshing_demo1[2043:102101] tempString:0x7fff58006738 strongString:0x7fc6d4d0d0b0 copyString:0x7fc6d4d0d0a8

由此我們可以看到結(jié)果了,copy 屬性并沒有改變自己的內(nèi)存地址和值,而strong屬性的內(nèi)存地址指向了tempString。這樣應(yīng)該很好的理解兩個屬性的差異了吧。可以根據(jù)自己的項目需要進行相應(yīng)的操作,不過一般大家都是用copy的,(做自己不好嗎,跟別人一樣沒意思 ,hahaha...)無他,都不想跳進坑里面而已。我們再看看把tempString換成 NSString類型會怎么樣。

    NSString *tempString = [NSString stringWithFormat:@"original"];
    self.s_String = tempString;
    self.c_String = tempString;
    
    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);
    
    tempString = @"change";

    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);
2017-09-11 23:02:34.166 Refreshing_demo1[2114:108457] tempString:original strongString:original copyString:original
2017-09-11 23:02:34.166 Refreshing_demo1[2114:108457] tempString:0xa000c505a04b2028 strongString:0xa000c505a04b2028 copyString:0xa000c505a04b2028
2017-09-11 23:02:34.166 Refreshing_demo1[2114:108457] tempString:0x7fff5f4bc738 strongString:0x7f9990d0c8f0 copyString:0x7f9990d0c8e8

2017-09-11 23:02:34.167 Refreshing_demo1[2114:108457] tempString:change strongString:original copyString:original
2017-09-11 23:02:34.167 Refreshing_demo1[2114:108457] tempString:0x100757b90 strongString:0xa000c505a04b2028 copyString:0xa000c505a04b2028
2017-09-11 23:02:34.167 Refreshing_demo1[2114:108457] tempString:0x7fff5f4bc738 strongString:0x7f9990d0c8f0 copyString:0x7f9990d0c8e8

如果在這樣子的一個情況下,copystrong屬性并不會有什么分別,所以有時候我們把字符串定義成copy或者strong,都不會有什么影響,不過我們寫代碼還是要嚴謹一點,該用什么就用什么。

接下來我們看看下面這種的請寫法會怎么樣。

    NSMutableString *tempString = [NSMutableString stringWithFormat:@"original"];
    _s_String = tempString;
    _c_String = tempString;
    
    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);
    
    [tempString appendString:@"change"];

    NSLog(@"tempString:%@ strongString:%@ copyString:%@",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",tempString,_s_String,_c_String);
    NSLog(@"tempString:%p strongString:%p copyString:%p",&tempString,&_s_String,&_c_String);
2017-09-11 23:15:51.344 Refreshing_demo1[2172:112713] tempString:original strongString:original copyString:original
2017-09-11 23:15:51.345 Refreshing_demo1[2172:112713] tempString:0x6080000795c0 strongString:0x6080000795c0 copyString:0x6080000795c0
2017-09-11 23:15:51.345 Refreshing_demo1[2172:112713] tempString:0x7fff5cb3b738 strongString:0x7fc545d0b6d0 copyString:0x7fc545d0b6c8

2017-09-11 23:15:51.345 Refreshing_demo1[2172:112713] tempString:originalchange strongString:originalchange copyString:originalchange
2017-09-11 23:15:51.345 Refreshing_demo1[2172:112713] tempString:0x6080000795c0 strongString:0x6080000795c0 copyString:0x6080000795c0
2017-09-11 23:15:51.346 Refreshing_demo1[2172:112713] tempString:0x7fff5cb3b738 strongString:0x7fc545d0b6d0 copyString:0x7fc545d0b6c8

如果我們不用self.點語法,這樣就不會調(diào)用 getter setter 方法,copy也就不會起作用了,連class類型都發(fā)生了變化,有時候因為類型發(fā)生了變化,導致程序無法識別而crash掉。
以下是這位開發(fā)者對于self 跟下劃線_的講解

[鐘穎Cyan](https://www.zhihu.com/people/ios_dev)
iOS/Mac 開發(fā)者,Pin / TodayMind / 小歷

_xxx訪問的是xxx的地址。self.xxx訪問的是xxx的getter。
這兩者并不是完全等價的,self.xxx是用objc_msgSend發(fā)消息,_xxx或者self->xxx則是直接訪問內(nèi)存地址,
一般建議在init里面用_xxx,其他地方用self.xxx,為什么呢?避免踩坑

所以用self.xxx 或者下劃線_xxx,都有很大學問。這里還可以引申至NSArraycopy, NSMutableArraystrong 或一些其他類型,So 大家在寫代碼的時候就要注意了,代碼的寫法習慣真的很重要,直接影響項目的穩(wěn)定性,所以大家在寫代碼的時候,該用什么屬性就用什么屬性,菜逼與大牛之間只是一線之差??。

嗯!今天就到這里,下期再見??

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容