阅前提示:
本文首次写作比较早,但是对于本文探索的内存管理这一块儿,在本次发布时依然适用,相信也会在后续很长时间内不会有所改变,读者可以放心。
开发环境:
Mac系统版本:macOS Mojave 10.14(18A391)
Xcode:Version 10.0 (10A255)
结论:
就怕你想看结论又不想看长篇大论,就把结论写到上面,免得你滑屏幕累得慌
探索:
1. 为什么assign不能用来修饰对象类型?
我先引用 故胤道长 在《iOS面试之道》这本书中的回答:
assign 修饰的对象被释放后,指针的地址依然存在,造成野指针,在堆上容易造成崩溃。而栈上的内存系统会自动处理,不会造成野指针。
总之一句话,使用assign修饰对象容易造成崩溃。
代码验证环节:
控制台输出:
2. 使用copy和strong修饰NSString、NSArray这类有对应可变类型的对象类型有什么区别?
在对对象赋值的时候,如果是使用copy修饰,那么会在内存中将原对象的值拷贝一份,原对象与该对象指向的是不同的内存区域,原对象在之后做任何修改都与该对象无关;
而如果是使用strong修饰,那么该对象与原对象虽然是不同的指针对象,但指向的都是同一片内存区域,如果原对象进行了修改,那么即使这个对象是不可变的,它的值也会发生变化;
代码验证环节:
控制台输出:
3. 为什么说weak修饰的对象会自行在内存中销毁?
这就没啥说的了,直接代码验证:
控制台输出:
4. 为什么不能用copy修饰NSMutableString这种可变对象?
控制台输出:
上面的代码执行后,会导致崩溃,可以看到上面控制台输出的崩溃记录,崩溃的原因是 Attempt to mutate immutable object with appendString:,这句话的意思是 `尝试用附件字符串来改变不可变对象:`,我们创建的对象明明是可变的,为什么在改变的时候却因为该对象不可改变而崩溃呢?其实这就是copy的贡献了。接下来我们输出他们赋值之后的类型你就会明白了,看下图。
看到了吗?经过赋值之后strong修饰的对象依然是NSMutableString,然而copy修饰的对象却变成了NSString,这是为什么呢? 其实,这是因为所有的这种可变类型都是继承对应的不可变类型,然而,却没有重写不可变类型的copy方法,当使用copy修饰的时候,调用不可变类型的copy方法,得到的其实是一个不可变的对象,此时,我们去修改它,自然就会报错了。
结尾:
最近在看唐巧大神和故胤道长一起写的《iOS面试之道》和《Objective-C高级编程 iOS与OS X多线程和内存管理》这两本书,突然心血来潮,以前没仔细研究过,这次就研究了一下,把不定期更新的博客更新一下,有用你就给个喜欢,没用就当看个热闹,想认识交流技术的就关注一下。