没有比这里更全的了,看我就好了
面试官😃 :介绍下ARC下,常用的属性修饰符及其作用?
assign,strong,copy,weak
atmoic/nonatomic 安全策略
reawrite/readonly 读写策略,访问权限
assign: 修饰基本数据类型(比如int,double,bool等),不涉及引用计数的改变!
strong:表示指向并持有该对象,其修饰对象的引用计数加1!只要对象的引用计数不为0,就不会被销毁!用于修饰oc对象!
copy:浅拷贝,生成新的指针指向元对象的内存地址,修饰NSString/NSDictionary/NSArray/NSSet类型!
weak:表示指向但不持有该对象,引用计数不会加1。修饰的对象在释放后,weak类型指针自动置为nil,是一种弱引用。用于修饰代理或者用来解决循环引用!(oc的特定对nil对象发送消息,不会crash)
面试官😃 :介绍下strong和weak的区别?
当一个对象没有strong类型的指针指向它,它就会被释放,即使有weak指针指向它,weak指针也会被清除。当weak指针指向的对象释放后,weak指针自动置为nil。
面试官😃 :使用assign修饰对象会怎样?
oc基本数据类型和数据类型一般分配到栈上,生命周期(内存)由系统管理。
程序员自己创建的对象分配到堆上,生命周期(内存)由程序员自己管理。
使用assign修饰对象可能会遇到下面两个问题,
问题一
Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT) 野指针
问题二(不好测试)
[xxx methodA] unrecognized selector sent to instance 0x1xxxxxxxx 找不到方法
举例说明:
DDObject.h
#import
NS_ASSUME_NONNULL_BEGIN @interface DDObject : NSObject @property (nonatomic, assign) int age; - (void)eat; @end NS_ASSUME_NONNULL_END DDObject.m
#import "DDObject.h" @implementation DDObject - (void)eat { } @end
ViewController.m
在编译时期,xcode报告了一个警告
Assigning retained object to unsafe property; object will be released after assignment (将保留对象赋值给不安全属性;对象赋值后将被释放)
29行代码
声明一个在栈上的指针,
43行代码
创建DDObject对象,self.ddObj指向这个对象的内存地址,由于没有强指针指向这个对象,所以这个对象创建后就被释放了,此时self.ddObj指向的这块内存地址会出现两种情况:一:空闲地址(即没有被其他对象申请并占用)此地址空间在对象释放时被标记为空闲地址,二:被其他对象申请并占用了(这个不好测试,就不掩饰了)。
45行代码
找到self.ddObj指针指向的内存地址中的对象,并取出其对象的age属性。根据43行的分析,一:此地址空间是空闲地址,什么都没有,所以过掉45行代码就会报错,异常坏的访问
总结如下:使用assign修饰对象,可能会造成野指针异常或者出现找不到方法的异常。因为对象释放后,该对象占用的内存可能被标记为空闲地址,或者被其他对象申请并占用,但是指针还是存在的(指针没有被置为nil),下次在访问该对象就会造成野指针异常。(如果被其他对象申请并占用,就可能会报告找不到方法的异常)!
面试官😃 :weak指针自动置为nil的实现原理?
请看这里https://www.jianshu.com/p/13c4fb1cedea
weak指针不会增加引用计数,并在引用对象被回收的时候自动被置为nil
Runtime维护了一个weak表,用于存储指向某个对象的所有weak指针。weak表其实是一个哈希表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。
weak 的实现原理可以概括一下三步
1、初始化时:runtime会调用objc_initWeak函数,初始化一个新的weak指针指向对象的地址。
2、添加引用时:objc_initWeak函数会调用 objc_storeWeak() 函数,objc_storeWeak() 的作用是更新指针指向,创建对应的弱引用表。
3、释放时,调用clearDeallocating函数。clearDeallocating函数首先根据对象地址获取所有weak指针地址的数组,然后遍历这个数组把其中的数据设为nil,最后把这个entry从weak表中删除,最后清理对象的记录。当weak引用指向的对象被释放时,如何去处理weak指针?
1、调用objc_release
2、因为对象的引用计数为0,所以执行dealloc
3、在dealloc中,调用了_objc_rootDealloc函数
4、在_objc_rootDealloc中,调用了object_dispose函数
5、调用objc_destructInstance
6、最后调用objc_clear_deallocating
简单来说:
a. 从weak表中获取被释放对象的地址为键值的记录
b. 将包含在记录中的所有附有 weak修饰符变量的地址,赋值为 nil
c. 将weak表中该记录删除
d. 从引用计数表中删除废弃对象的地址为键值的记录
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)