属性声明
// ByteDancer.h
@interface ByteDancer: NSObject
@property (nonatomic, copy) NSString* name;
@end
- 可以透过点符号访问属性
- 自动声明的变量是带下划线的
属性关键字
分类
分类 |
属性关键字 |
原子性 |
atomic(默认值)、nonatomic |
读写权限 |
readwrite(默认值)、readonly、setter、getter |
内存管理 |
assign(默认值)、weak、unsafe_unretained、retain、strong、copy |
可空性 |
(nullable、_Nullable 、__nullable)、(nonnull、_Nonnull、__nonnull)、(null_unspecified、_Null_unspecified 、__null_unspecified)、null_resettable |
原子性
属性关键字 |
用法 |
atomic |
原子性(默认),编译器会自动生成互斥锁,对 setter 和 getter 方法进行加锁,可以保证属性的赋值和取值的原子性操作是线程安全的,但不包括操作和访问。比如说 atomic 修饰的是一个数组的话,那么我们对数组进行赋值和取值是可以保证线程安全的。但是如果我们对数组进行操作,比如说给数组添加对象或者移除对象,是不在 atomic 的负责范围之内的,所以给被 atomic 修饰的数组添加对象或者移除对象是没办法保证线程安全的。 |
nonatomic |
非原子性,一般属性都用 nonatomic 进行修饰,因为 atomic 非常耗时。 |
读写权限
属性关键字 |
用法 |
readwrite |
可读可写(默认),同时生成 setter 方法和 getter 方法的声明和实现。 |
readonly |
只读,只生成 getter 方法的声明和实现。 |
setter |
可以指定生成的 setter 方法名,如 setter = setName。 |
getter |
可以指定生成的 getter 方法名,如 getter = getName。 |
内存管理
属性关键字 |
用法 |
assign |
1. 既可以修饰基本数据类型,也可以修饰对象类型;2. setter 方法的实现是直接赋值,一般用于基本数据类型 ;3. 修饰基本数据类型,如 NSInteger、BOOL、int、float 等;4. 修饰对象类型时,不增加其引用计数;5. 会产生悬垂指针(悬垂指针:assign 修饰的对象在被释放之后,指针仍然指向原对象地址,该指针变为悬垂指针。这时候如果继续通过该指针访问原对象的话,就可能导致程序崩溃)。 |
weak |
1. 只能修饰对象类型;2. ARC 下才能使用;3. 修饰弱引用,不增加对象引用计数,主要可以用于避免循环引用;4. weak 修饰的对象在被释放之后,会自动将指针置为 nil,不会产生悬垂指针。 |
unsafe_unretained |
1. 既可以修饰基本数据类型,也可以修饰对象类型;2. MRC 下经常使用,ARC 下基本不用;3. 同 weak,区别就在于 unsafe_unretained 会产生悬垂指针。 |
retain |
1. MRC 下使用,ARC 下基本使用 strong;2. 修饰强引用,将指针原来指向的旧对象释放掉,然后指向新对象,同时将新对象的引用计数加1;3. setter 方法的实现是 release 旧值,retain 新值,用于OC对象类型。 |
strong |
1. ARC 下才能使用;2. 原理同 retain;3. 但是在修饰 block 时,strong 相当于 copy,而 retain 相当于 assign。 |
copy |
setter 方法的实现是 release 旧值,copy 新值,用于 NSString、block 等类型。 |
可空性
Objective-C 中没有可选类型,NSString * 既可以表示这个类型是 optional,也可以表示是 non-optional。这样在混编时就产生了一个问题,Swift 编译器并不知道一个 Objective-C 指针类型到底是 optional 还是 non-optional。在这种情况下,编译器会将 Objective-C 的指针类型当成是 隐式解析可选类型(例如 String!)导入到 Swift 中。
因此,Apple 为 Objective-C 引入了 nullability annotations 特性,为 Objective-C API 指定可空性,可以控制 Objective-C 声明中的指针类型如何导入到 Swift 中(以 optional 还是 non-optional),让混编更安全;同时,也给 Objective-C 新增了 nullability 类型警告,让 Objective-C 代码更加规范。
可空性限定符 |
导入到 Swift 中 |
意义 |
nullable、_Nullable 、__nullable |
optional,如 String? |
该值可以是 nil |
nonnull、_Nonnull、__nonnull |
non-optional,如 String |
该值永远不会为 nil |
null_unspecified、_Null_unspecified 、__null_unspecified |
隐式解析 optional,如 String! |
未指定值是否可以 nil(非常罕见,除非将其作为过渡工具,否则应避免使用)。使用该限定符的结果和不使用 nullability annotations 特性的结果是一样的,我认为该限定符的作用是在过渡时抵消 audited Regions |
null_resettable(只用于属性) |
隐式解析 optional,如 String! |
1. 属性的 setter 允许设置 nil 以将值重置为某个默认值,但其 getter 永远不会返回 nil(因为提供了一个默认值); 2. 必须重写 setter 或 getter 做非空处理。否则会报警告 Synthesized setter 'setName:' for null_resettable property 'name' does not handle nil,同时存在安全隐患 |
所有权修饰符
所有权修饰符 |
用法 |
__strong |
1. 强引用持有对象,可以对应 strong、retain、copy 关键字。2. 编译器将为 strong、retain、copy 修饰的属性生成带 __strong 所有权修饰符的实例变量。 |
__weak |
1. 弱引用持有对象,对应 weak 关键字,ARC下用来防止循环引用。2. 编译器将为 weak 修饰的属性生成带 __weak 所有权修饰符的实例变量。 |
__unsafe_unretained |
1. 弱引用持有对象,对应 unsafe_unretained、assign 关键字,MRC下用来防止循环引用。2. 编译器将为 unsafe_unretained 修饰的属性生成带 __unsafe_unretained 所有权修饰符的实例变量。3. 与 __weak 相比,它不需要遍历 weak 表来检查对象是否 nil,性能上要更好一些。但是它会产生悬垂指针。 |
__autoreleasing |
在 MRC 中我们可以给对象发送 autorelease 消息来将它注册到 autoreleasepool 中,而在 ARC 中我们可以使用 __autoreleasing 修饰符修饰对象将对象注册到 autoreleasepool 中。 |
OC - 属性关键字和所有权修饰符
Objective-C属性(property)的特性(attribute)