- assign
assign 一般用來修飾基礎(chǔ)類型,如 float 锡宋,double儡湾,int ,NSInteger等执俩。
它也可以用來修飾對(duì)象徐钠,但是assign 修飾對(duì)象有個(gè)問題,就是當(dāng)對(duì)象的引用計(jì)數(shù)器為0時(shí)役首,不會(huì)主動(dòng)將對(duì)象置空尝丐,如果我們沒有手動(dòng)處理的話,就會(huì)造成野指針衡奥,導(dǎo)致程序崩潰
- weak
對(duì)于weak爹袁,我們都知道它是用來修飾 OC對(duì)象的,是弱引用矮固,在對(duì)象的引用計(jì)數(shù)器等于0的時(shí)候失息,會(huì)將對(duì)象的指針 置為空。
- strong
強(qiáng)引用档址,我們?cè)谟胹trong 修飾屬性的時(shí)候盹兢,我們可以理解為 是對(duì)對(duì)象的 直接引用。
類似于守伸,我有一個(gè)蘋果绎秒,你想用我的蘋果,我把我的蘋果交到你的手里尼摹,然后你把蘋果咬了一口见芹,其實(shí)那是我的蘋果被咬了一口剂娄,你還我的時(shí)候,我的蘋果已經(jīng)不完整了玄呛。
也就是說我們用 strong 修飾的屬性阅懦,無論我們?cè)谀睦锔膭?dòng)他了,改變的都是最初的他把鉴。(利用這個(gè)特性我們可以做很多事故黑,尤其是跨多個(gè)頁面刷新本地緩存的功能)案例:AViewController 和 BViewController 都持有屬性 User對(duì)象
AViewController.m@interface AViewController () @property (nonatomic ,strong) User *auser; @end //A 調(diào)用pushToBViewControler 跳轉(zhuǎn)B 將auser 傳值給buser儿咱,auser 是實(shí)例對(duì)象 -(void)pushToBViewControler{ BViewController *bVC = [[BViewController alloc]init]; bVC.buser = self.auser; [self.navigationController pushViewController:bVC animated:YES]; }
BViewController.h
@interface BViewController : UIViewController @property (nonatomic ,strong) User *buser; @end
BViewController.m
-(void)changeUserValue{ self.buser.name = @"buser"; self.buser.sex = @"bsex"; }
當(dāng)BViewController 調(diào)用 changeUserValue 后庭砍,AViewController 的auser對(duì)象的值實(shí)際上已經(jīng)發(fā)生了改變,auser就是我的蘋果混埠,buser就是我給你蘋果,關(guān)系如下:
self.buser => 同一內(nèi)存地址 <= self.auser
- copy
copy 直譯為拷貝怠缸,拷貝在使用時(shí)有兩種實(shí)現(xiàn)方式,copy 和 mutableCopy钳宪, 而拷貝又分兩種拷貝類型揭北,深拷貝 和 淺拷貝 。
深拷貝:指針復(fù)制吏颖,創(chuàng)建新的指針地址搔体,內(nèi)容復(fù)制
淺拷貝:內(nèi)容復(fù)制,指針地址不變關(guān)于 copy 和 mutableCopy
如果是可變字符串或者是可變數(shù)組或者可變字典半醉,無論使用 copy 還是 mutableCopy 都會(huì)創(chuàng)建新的內(nèi)存地址疚俱,也就是深拷貝
如果是不可變的,使用copy是淺拷貝缩多,mutableCopy是深拷貝
另外:
使用 copy 的話呆奕,無論深淺拷貝,拷貝出來的對(duì)象都是不可變的衬吆。
使用 mutableCopy 梁钾,拷貝出來的對(duì)象是可變的。如果是不可變字符串或者是不可變數(shù)組逊抡,使用 copy 不會(huì)創(chuàng)建新的內(nèi)存地址姆泻,效果上和strong是一樣的,地址不變冒嫡,內(nèi)容相等麦射,也就是淺拷貝。 使用 mutableCopy 則會(huì)創(chuàng)建新的內(nèi)存地址灯谣,也就是深拷貝潜秋。
注意:對(duì)于
NSString * test = @"this is a test string"
來說@"this is a test string"
本身就是一個(gè)字符串對(duì)象,他有自己內(nèi)存地址胎许,當(dāng)我們?cè)俅谓otest
賦值時(shí)峻呛,其實(shí)是把新的字符串對(duì)象賦給了test
罗售,測(cè)試的test
擁有了一個(gè)新的內(nèi)存地址。示例如下NSString * test = @"this is a test string"; NSLog(@"\n舊地址:%p",test); test = @"this is a new test string"; NSLog(@"\n新地址:%p",test);
打印結(jié)果
2020-03-07 19:34:59.555045+0800 BSFramwork[44914:558760] 舊地址:0x100f2add8 2020-03-07 19:34:59.555138+0800 BSFramwork[44914:558760] 新地址:0x100f2ae18
但是對(duì)于
NSMutableString
來說钩述,在同一個(gè)可變字符串地址不變的情況下寨躁,我們是可以更改其value的NSMutableString * test = [[NSMutableString alloc]initWithString: @"this is a test string"]; NSLog(@"\n舊地址:%p",test); [test setString:@"this is a new test string"]; NSLog(@"\n新地址:%p",test);
打印結(jié)果
2020-03-07 19:40:47.748088+0800 BSFramwork[44938:562658] 舊地址:0x600002510bd0 2020-03-07 19:40:47.748192+0800 BSFramwork[44938:562658] 新地址:0x600002510bd0
無論是字符串還是數(shù)組,只要涉及到可變不可變的牙勘,都會(huì)有這樣的問題职恳,從本質(zhì)上來說,只有 “可變的” , 才能在不更改其內(nèi)存地址時(shí)更改其 value 方面,不可變的 是無法直接改變 value 的放钦,只能通過賦值新的對(duì)象來賦予他新的value。
綜上所述恭金,我們來說下為什么
NSString NSMutableString NSArray NSMutableArray
類型使用copy
修飾
原因:簡(jiǎn)單點(diǎn)說操禀,如果我們使用strong
來修飾這幾種類型話,如下操作:NSMutableString * test = [[NSMutableString alloc]initWithString: @"test string"]; self.cStr = test; //由于業(yè)務(wù)原因横腿,進(jìn)行一系列操作颓屑,最后對(duì) test重新賦值,//但是也無需求需要 //self.cStr依然需要等于初始值 [test setString:@"this is a new test string"];
由于我們使用
strong
修飾耿焊,self.cStr
的內(nèi)存地址和test
是一個(gè)地址揪惦,而test改變了其value,從而導(dǎo)致self.cStr
的value也發(fā)生了改變罗侯,這個(gè)時(shí)候我們就需要使用copy器腋,因?yàn)?code>test是NSMutableString
類型,使用copy修飾self.cStr
擁有了新的內(nèi)存地址歇父,value值和test
初始值相同蒂培,雖然后邊test
值被更改,但是由于內(nèi)存地址不相同榜苫,是屬于兩個(gè)對(duì)象护戳,所以并不會(huì)影響self.cStr
之前賦的值
問題&疑惑
對(duì)于NSString NSMutableString NSArray NSMutableArray
類型,我在使用 weak 修飾的時(shí)候發(fā)現(xiàn)和 strong 基本一樣垂睬,那為什么 NSString NSMutableString NSArray NSMutableArray
在特定需求下不使用 weak 而是使用strong 修飾媳荒,這個(gè)我還不太懂。
補(bǔ)充:最近有看過weak的實(shí)現(xiàn)源碼驹饺,weak會(huì)涉及到__weak的問題钳枕,需要進(jìn)行大量的操作。如果使用weak赏壹,對(duì)性能的需求是要大于strong的鱼炒,可能是這個(gè)原因?qū)е碌模@個(gè)只是猜測(cè)蝌借。
如果有哪位同行知道原理或者猜測(cè)可能昔瞧,希望能講解一二指蚁。
如果是我們自定義的對(duì)象,是不能用 weak 來聲明的自晰,編譯器會(huì)直接報(bào)錯(cuò)凝化。
報(bào)錯(cuò)原因:如果我們用 weak 修飾,雖然進(jìn)行了賦值或者初始化操作酬荞,但是引用計(jì)數(shù)器是不會(huì)加一的搓劫,當(dāng)出了作用域,對(duì)象就會(huì)銷毀混巧,指針置空枪向,這樣我們所持有的屬性(對(duì)象)就是野指針。
但是不清楚為什么NSString NSMutableString NSArray NSMutableArray
是沒問題的牲剃。
如果說遣疯,直接賦值雄可,而不是 alloc 或者 new 去創(chuàng)建的我們還可以認(rèn)為他分配的內(nèi)存區(qū)域不同導(dǎo)致的凿傅,但是我在使用 alloc 去創(chuàng)建的時(shí)候,發(fā)現(xiàn)也沒問題数苫,暈啊啊啊啊啊~~~~