背景
??????在測試中發(fā)現(xiàn)有個(gè)網(wǎng)頁沒有加載出來,查找原因時(shí),發(fā)現(xiàn)是由于用了weak
修飾了一個(gè)NSURL
的全局變量哮内,出了方法作用域之后祈噪,這個(gè)NSURL
的全局變量的值就變?yōu)?code>nil了泽铛,因此網(wǎng)頁才沒能加載成功。
思考和實(shí)踐
??????對于weak
這個(gè)修飾符辑鲤,之前并沒有做的太多的學(xué)習(xí)和研究盔腔,只是知道在修飾UI控件以及代理的時(shí)候使用。
??????做了一個(gè)簡單的測試月褥,分別用weak
修飾NSArray
弛随、NSMutableArray
、NSDictionary
宁赤、NSMutableDictionary
舀透、NSURL
,其中數(shù)組和URL
在另一個(gè)方法中調(diào)用是都為nil
了决左,但字典仍可以正常的存取值愕够。至于為什么會(huì)出現(xiàn)這種結(jié)果,不得而知佛猛,如果有哪位小伙伴知道原理還請?jiān)谠u(píng)論區(qū)留言惑芭。對于OC中的對象建議還是使用strong
或者copy
進(jìn)行修飾,以免因?yàn)樽兞繛?code>nil而引起不必要的問題继找。
變量聲明
@property(nonatomic,weak)NSArray * weakArray;
@property(nonatomic,weak)NSMutableArray * weakMutableArray;
@property(nonatomic,weak)NSDictionary * weakDictionary;
@property(nonatomic,weak)NSMutableDictionary * weakMutableDictionary;
@property(nonatomic,weak)NSURL * weakUrl;
運(yùn)行結(jié)果
NSArray * weakArray = [NSArray arrayWithObject:@"weakArray"];
self.weakArray = weakArray;
NSLog(@"viewDidLoad方法中 weakArray = %@ %p",self.weakArray,self.weakArray);// viewDidLoad方法中 weakArray = (weakArray) 0x600003534a10
NSMutableArray * weakMutableArray = [NSMutableArray arrayWithObject:@"weakMutableArray"];
self.weakMutableArray = weakMutableArray;
NSLog(@"viewDidLoad方法中 weakMutableArray = %@ %p",self.weakMutableArray,self.weakMutableArray);//viewDidLoad方法中 weakMutableArray = (weakMutableArray) 0x60000396e130
NSLog(@"字典");
NSDictionary * weakDictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"weakDictionary",@"weak",nil];
self.weakDictionary = weakDictionary;
NSLog(@"viewDidLoad方法中 weakDictionary = %@ %p",self.weakDictionary,self.weakDictionary);//viewDidLoad方法中 weakDictionary = {weak = weakDictionary;} 0x6000022611c0
NSMutableDictionary * weakMutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"weakMutableDictionary",@"weak",nil];
self.weakMutableDictionary = weakMutableDictionary;
NSLog(@"viewDidLoad方法中 weakMutableDictionary = %@ %p",self.weakMutableDictionary,self.weakMutableDictionary);// viewDidLoad方法中 weakMutableDictionary = {weak = weakMutableDictionary;} 0x6000037701a0
NSURL * weakUrl = [NSURL URLWithString:@"weakUrl"];
self.weakUrl = weakUrl;
NSLog(@"viewDidLoad方法中 weakUrl = %@ %p",self.weakUrl,self.weakUrl);// viewDidLoad方法中 weakUrl = weakUrl 0x600001419a40
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
NSLog(@"viewWillAppear方法中 weakArray = %@ %p",self.weakArray,self.weakArray);// viewWillAppear方法中 weakArray = (null) 0x0
NSLog(@"viewWillAppear方法中 weakMutableArray = %@ %p",self.weakMutableArray,self.weakMutableArray);// viewWillAppear方法中 weakMutableArray = (null) 0x0
NSLog(@"viewWillAppear方法中 weakDictionary = %@ %p",self.weakDictionary,self.weakDictionary);//viewWillAppear方法中 weakDictionary = {weak = weakDictionary;} 0x6000022611c0
NSLog(@"viewWillAppear方法中 weakMutableDictionary = %@ %p",self.weakMutableDictionary,self.weakMutableDictionary);// viewWillAppear方法中 weakMutableDictionary = {weak = weakMutableDictionary;} 0x6000037701a0
NSLog(@"viewWillAppear方法中 weakUrl = %@ %p",self.weakUrl,self.weakUrl);// viewWillAppear方法中 weakUrl = (null) 0x0
}
copy和strong修飾數(shù)組
- 當(dāng)源對象為不可變數(shù)組時(shí)强衡,不管是可變還是不可變數(shù)組,使用
copy
或strong
進(jìn)行修飾時(shí),最終數(shù)組都會(huì)變?yōu)椴豢勺償?shù)組漩勤,內(nèi)存地址不變感挥。 - 當(dāng)源對象為可變數(shù)組時(shí)
- 使用
copy
修飾可變數(shù)組或者不可變數(shù)組時(shí),即使聲明的是可變數(shù)組越败,最終變?yōu)橐粋€(gè)新的不可變數(shù)組触幼,如果這時(shí)調(diào)用可變數(shù)組的方法,像addObject
究飞、removeObject
等方法時(shí)置谦,會(huì)導(dǎo)致程序崩潰,因?yàn)椴豢勺償?shù)組沒有這些方法亿傅。 - 使用
strong
修飾不可變數(shù)組時(shí)媒峡,最終數(shù)組都會(huì)變?yōu)椴豢勺償?shù)組,內(nèi)存地址不變葵擎。這時(shí)候仍然可以調(diào)用可變數(shù)組的方法谅阿,不過不能直接調(diào)用,需要強(qiáng)轉(zhuǎn)或者使用performSelector:withObject:
這種方式酬滤。 - 使用
strong
修飾可變數(shù)組時(shí)签餐,數(shù)組依然是可變數(shù)組,內(nèi)存地址不變盯串。
@property(nonatomic,copy)NSArray * coArray;
@property(nonatomic,copy)NSMutableArray * coMutableArray;
@property(nonatomic,strong)NSArray * strongArray;
@property(nonatomic,strong)NSMutableArray * strongMutableArray;
NSArray * array = [NSArray arrayWithObject:@"array"];
NSLog(@"%@ %p",[array class],array); // __NSSingleObjectArrayI 0x6000015937a0
self.coArray = array;
self.coMutableArray = array;
self.strongArray = array;
self.strongMutableArray = array;
NSLog(@"%@ %p",[self.coArray class],self.coArray); // __NSSingleObjectArrayI 0x6000015937a0
NSLog(@"%@ %p",[self.coMutableArray class],self.coMutableArray);// __NSSingleObjectArrayI 0x6000015937a0
NSLog(@"%@ %p",[self.strongArray class],self.strongArray);// __NSSingleObjectArrayI 0x6000015937a0
NSLog(@"%@ %p",[self.strongMutableArray class],self.strongMutableArray);// __NSSingleObjectArrayI 0x6000015937a0
NSMutableArray * mutableArray = [NSMutableArray arrayWithObject:@"mutableArray"];
NSLog(@"%@ %p",[mutableArray class],mutableArray);// __NSArrayM 0x6000019dd8c0
self.coArray = mutableArray;
self.coMutableArray = mutableArray;
self.strongArray = mutableArray;
self.strongMutableArray = mutableArray;
NSLog(@"%@ %p",[self.coArray class],self.coArray);// __NSSingleObjectArrayI 0x6000015935c0
NSLog(@"%@ %p",[self.coMutableArray class],self.coMutableArray);// __NSSingleObjectArrayI 0x600001593590
[self.coMutableArray addObject:@"coMutableArray"];// -[__NSSingleObjectArrayI addObject:]: unrecognized selector sent to instance
NSLog(@"%@ %p",[self.strongArray class],self.strongArray);// __NSArrayM 0x6000019dd8c0
NSLog(@"%@ %p",[self.strongMutableArray class],self.strongMutableArray);// __NSArrayM 0x6000019dd8c0
對象的copy與mutableCopy
- 當(dāng)源對象為不可變時(shí),使用
copy
時(shí)不會(huì)生成新的對象氯檐,即指針拷貝(淺拷貝);使用mutableCopy
會(huì)生成一個(gè)新的可變對象体捏,即對象拷貝(深拷貝)冠摄。 - 當(dāng)源對象為可變時(shí),使用
copy
和mutableCopy
時(shí)都會(huì)生成一個(gè)新的對象几缭,即對象拷貝(深拷貝)河泳,區(qū)別在于:使用copy
生成的對象為不可變的,而mutableCopy
生成的對象是可變的奏司。
測試代碼如下:
NSString * string = @"string";
NSLog(@"string = %@ %p",[string class],string);
// __NSCFConstantString 0x10eff20a0
NSLog(@"copyString = %@ %p",[[string copy] class],[string copy]);
// __NSCFConstantString 0x10eff20a0
NSLog(@"mutableCopyString = %@ %p",[[string mutableCopy] class],[string mutableCopy]);
// __NSCFString 0x600003f8e250
NSLog(@"NSMutableString\n");
NSMutableString * mutableString = [NSMutableString stringWithString:@"mutableString"];
NSLog(@"mutableString = %@ %p",[mutableString class],mutableString);
// __NSCFString 0x600003dfa670
NSLog(@"copy_mutableString = %@ %p",[[mutableString copy] class],[mutableString copy]);
// __NSCFString 0x6000033fc340
/**
這個(gè)地方不知道為什么打印的結(jié)果是可變字符串 乔询,做了一個(gè)測試樟插,調(diào)用可變字符串的appendString方法韵洋,崩潰了
NSMutableString * copy_mutableString = [mutableString copy];
[copy_mutableString appendString:@"append"];
NSLog(@"%@",copy_mutableString); // Attempt to mutate immutable object with appendString:
*/
NSLog(@"mutableCopy_mutableString = %@ %p",[[mutableString mutableCopy] class],[mutableString mutableCopy]);
// __NSCFString 0x600003dfa940
NSLog(@"NSArray\n");
NSArray * array = [NSArray arrayWithObject:@"array"];
NSLog(@"array = %@ %p",[array class],array);
// __NSSingleObjectArrayI 0x6000031a9960
NSLog(@"copy_array = %@ %p",[[array copy] class],[array copy]);
// __NSSingleObjectArrayI 0x6000031a9960
NSLog(@"mutableCopy_array = %@ %p",[[array mutableCopy] class],[array mutableCopy]);
// __NSArrayM 0x600003dfa310
NSLog(@"NSMutableArray\n");
NSMutableArray * mutablearray = [NSMutableArray arrayWithObject:@"mutablearray"];
NSLog(@"mutablearray = %@ %p",[mutablearray class],mutablearray);
// __NSArrayM 0x600003dfdb00
NSLog(@"copy_mutablearray = %@ %p",[[mutablearray copy] class],[mutablearray copy]);
// __NSSingleObjectArrayI 0x6000031bd0a0
NSLog(@"mutableCopy_mutablearray = %@ %p",[[mutablearray mutableCopy] class],[mutablearray mutableCopy]);
// __NSArrayM 0x600003dfd710
注:本文中的測試SDK版本為12.2,Xcode 10.2 黄锤,如有錯(cuò)誤歡迎留言指正搪缨。
參考文章
iOS內(nèi)存管理(6)--NSArray與NSMutableArray用copy修飾還是strong
assign weak retain strong copy關(guān)鍵字的區(qū)別
整理一下OC中的那些屬性修飾符
iOS Copy與MutableCopy 和 Copy與Strong 深度解析
iOS中copy和mutableCopy詳解
聊聊NSString為什么用copy
iOS學(xué)習(xí)——屬性引用self.xx與_xx的區(qū)別
iOS 同時(shí)重寫setter和getter時(shí)候報(bào)錯(cuò):Use of undeclared identifier '_name';did you mean 'name'
ios中set和get方法