iOS 属性修饰符面试题

iOS 属性修饰符面试题,第1张

没有比这里更全的了,看我就好了

面试官😃 :介绍下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. 从引用计数表中删除废弃对象的地址为键值的记录

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/994713.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存