weak、strong、@ property

面试题:weak实现原理?

一、weak

weak 基本用法

weak 是弱引用,用 weak 来修饰、描述所引用对象的计数器并不会增加,而且 weak 会在引用对象被释放的时候自动置为 nil,这也就避免了野指针访问坏内存而引起奔溃的情况,另外 weak 也可以解决循环引用。

为什么修饰代理使用 weak 而不是用 assign?

assign 可用来修饰基本数据类型,也可修饰 OC 的对象,但如果用 assign 修饰对象类型指向的是一个强指针,当指向的这个指针释放之后,它仍指向这块内存,必须要手动给置为 nil,否则会产生野指针,如果还通过此指针操作那块内存,会导致 EXC_BAD_ACCESS 错误,调用了已经被释放的内存空间;而 weak 只能用来修饰 OC 对象,而且相比 assign 比较安全,如果指向的对象消失了,那么它会自动置为 nil,不会导致野指针。

weak 原理概括

weak 表其实是一个哈希表,key 是所指对象的指针,value 是 weak 指针的地址数组。(value 是数组的原因是:因为一个对象可能被多个弱引用指针指向)

Runtime 维护了一张 weak 表,用来存储某个对象的所有的 weak 指针。

2、strong

strong表示属性对修饰的对象有一个强引用,会先保留新值,然后释放旧值。只能修饰对象

weak表示属性对修饰的对象有一个弱引用,对于新值不会增加引用计数,对于旧值也不会减少引用计数。当修饰的对象被释放时,weak修饰的属性被自动被置为nil,能够有效防止野指针错误。

weak常用于防止循环引用

3、@property 深入理解

@property = ivar + getter + setter

其中ivar是实例变量,编译器会帮我们自动生成名字为‘_属性名’这样的实例变量,同时自动生成getter和setter方法。

编译器帮我们做的事情

当我们声明一个属性后,编译器会将当前关键字修饰的属性自动生成setter方法和getter方法。

@property (nonatamic, copy) NSString *name; 等价于

-(void)setName:(NSString*)name{_name=name.copy;}

-(NSString*)name{return_name;}

编译器以上的工作我们称之为属性自动合成

@synthesis

iOS6以后LLVM编译器引入property autosynthesis,即属性自动合成,就是编译器会为每个@property添加@synthesis,如下

@synthesize propertyName = _propertyName;

如果不存在_propertyName实例变量,则会创建一个_propertyName,如果已经存在,则不会添加实例变量

@synthesis使用场景

以下场景自动合成会失效,需要手动合成

什么情况下自动合成会失效 ?

同时重写了属性的setter和getter时;

重写了只读属性的getter时;

使用了@dynamic时;

在@protocol中定义的所有属性;

在 category 中定义的所有属性;

父类已有的属性,子类重载的属性不会自动合成;

@dynamic

@dynamic 告诉编译器,不要为property声明的属性添加setter/getter方法, 由用户自己实现,该属性的getter和setter方法可能不在本类,而在其他地方(比如父类或者在运行时中提供, 如果不实现的话, 运行时会有Unrecoginzed Selector Crash)

你可能感兴趣的:(weak、strong、@ property)