@property:
编译器自动编写访问这些属性的存取方法;(这个过程有编译器在编译期执行,所以编辑器里看不到这些“合成方法”的源代码)编译器还自动向类中添加适当类型的实例变量,并且在属性名前加下划线作为实例变量的名字。
@synthesize:
指定实例变量的名字。
@interface Person ()
@property NSString * firstName;
@property NSString * lastName;
@end
@implementation Person
//默认的实例变量的名字为 _firstName _lastName
@synthesize firstName = _myFirstName;
@synthesize lastName = _myLastName;
@end
@dynamic
告诉编译器:不要自动创建实现属性所用的实例变量,也不要为其创建存取方法。
注意:编译访问属性的代码时,即使编译器发现没有定义的存取方法,也不会报错,它相信这些方法能在运行期找到。如果运行期没有写存取方法,则程序会报错,
@interface Person ()
@property NSString * name;
@end
@implementation Person
@dynamic name;
@end
[Person setName:]: unrecognized selector sent to instance 0x7f9de5f12b90'
属性特质:
原子性:默认情况下(atomic),编译器合成的方法会通过锁定机制确保其原子性,同步锁开销较大,带来性能问题,一般情况下并不要求属性必须是原子,因为这并不能保证线程安全,若要实现线程安全,需要更为深层的锁定机制才行,例如,一个线程在多次读取某属性值的过程有别的线程同时改写该值,即便声明为atomic,还是会读到不同的属性。如果具备nonatomic,则不使用同步锁,如果不加锁,当其中一个线程正在改写某属性值时,另外一个线程也会突然闯入,把尚未改好的属性读取出来,发生这种情况,线程读到的属性值可能不对。
读写权限:
readwrite 拥有获取和设置方法。
readonly 仅拥有获取方法。
内存管理语义:
assign : 设置方法只会针对基础类型的简单赋值操作。
strong :定义一种拥有关系;设置新值时,先保留新值,并释放旧值,然后再将新值设置上去。
weak :定义一种非拥有关系;设置新值时,既不保留新值也不释放旧值;在所指对象遭到摧毁时,属性值会清空。
unsafe_unretained :定义非拥有关系;当目标对象遭到摧毁时,属性值不会自动清空。
copy :设置方法不保留新值,而将其拷贝。
方法名:
getter = <name> 指定获取方法方法名。
@property (nonatomic,assign,getter=isOn) BOOL on;
setter = <name> 指定设置方法名。这种用法不常见。