修饰符weak引发的思考

背景

      在测试中发现有个网页没有加载出来,查找原因时,发现是由于用了weak修饰了一个NSURL的全局变量,出了方法作用域之后,这个NSURL的全局变量的值就变为nil了,因此网页才没能加载成功。

思考和实践

      对于weak这个修饰符,之前并没有做的太多的学习和研究,只是知道在修饰UI控件以及代理的时候使用。
      做了一个简单的测试,分别用weak修饰NSArrayNSMutableArrayNSDictionaryNSMutableDictionaryNSURL,其中数组和URL在另一个方法中调用是都为nil了,但字典仍可以正常的存取值。至于为什么会出现这种结果,不得而知,如果有哪位小伙伴知道原理还请在评论区留言。对于OC中的对象建议还是使用strong或者copy进行修饰,以免因为变量为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;

运行结果

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
}
viewdidload运行结果
viewwillappear运行结果
copy和strong修饰数组
  1. 当源对象为不可变数组时,不管是可变还是不可变数组,使用copystrong进行修饰时,最终数组都会变为不可变数组,内存地址不变。
  2. 当源对象为可变数组时
  • 使用copy修饰可变数组或者不可变数组时,即使声明的是可变数组,最终变为一个新的不可变数组,如果这时调用可变数组的方法,像addObjectremoveObject等方法时,会导致程序崩溃,因为不可变数组没有这些方法。
  • 使用strong修饰不可变数组时,最终数组都会变为不可变数组,内存地址不变。这时候仍然可以调用可变数组的方法,不过不能直接调用,需要强转或者使用performSelector:withObject:这种方式。
  • 使用strong修饰可变数组时,数组依然是可变数组,内存地址不变。
@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
  1. 当源对象为不可变时,使用copy时不会生成新的对象,即指针拷贝(浅拷贝);使用mutableCopy会生成一个新的可变对象,即对象拷贝(深拷贝)。
  2. 当源对象为可变时,使用copymutableCopy时都会生成一个新的对象,即对象拷贝(深拷贝),区别在于:使用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
/**
    这个地方不知道为什么打印的结果是可变字符串 ,做了一个测试,调用可变字符串的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 ,如有错误欢迎留言指正。
参考文章

iOS内存管理(6)--NSArray与NSMutableArray用copy修饰还是strong
assign weak retain strong copy关键字的区别
整理一下OC中的那些属性修饰符

iOS Copy与MutableCopy 和 Copy与Strong 深度解析
iOS中copy和mutableCopy详解
聊聊NSString为什么用copy

iOS学习——属性引用self.xx与_xx的区别
iOS 同时重写setter和getter时候报错:Use of undeclared identifier '_name';did you mean 'name'
ios中set和get方法

iOS 底层解析weak的实现原理(包含weak对象的初始化,引用,释放的分析)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352