0x00 引用自禅与 Objective-C 编程艺术与刘亚芳博客
0x01 属性的定义
属性都声明:使用@property声明属性
(例如:@property NSString*name;)
相当于@interface中声明里两个方法
- (void)setName:(NSString *)name;
-(NSString *)name;
0x02 属性的实现
属性的实现:使用@synthesize实现属性
(例如 :@synthesize name = _name)
相当于@implementtation实现里
- (void)setName:(NSString *)name;
- (NSString *)name;
0x03 属性的‘属性’
Objective-C提供属性的的是为了简化程序员编码
为属性提供了一些关键字用以控制setter、getter的实现细节
这些关键字我们称为属性的属性(attribute),一共3大类attribute。
1、读写性控制(readonly,readwrite,setter,getter)
如果读写性控制的关键字是readonly,是告诉编译器,只声明getter方法(无setter方法)
例如;@property(readonly)NSString *name;
等价于 - (NSString *)name;
如果是readwrite ,告诉编译器,即声明setter有声明getter
例如:@property(readwrite)NSString *name;
等价于 - (NSString *)name;
- (void)setName:(NSString *)name;
* readwrite是读写性控制的默认设置
2、原子性控制(nonatomic、atomic)
如果原子性控制的关键字是atomic。setter、getter方法在多线程访问下是绝对安全的,即setter、getter内部做了多线程访问处理,原子性控制的默认设置是atomic;
如果原子性控制的关键字是nonatomic,setter、getter方法内部不会做多线程访问处理,仅仅是普通多setter、getter方法;
程序开发过程中,setter、getter处处都在用,如果使用atomic,需要不断的对setter、getter加锁解锁以保证线程访问安全,会很占用系统资源,降低系统性能。
3、语义设置(assign,retain,copy)
如果语义设置对关键字是assign,setter、getter内部实现是直接赋值,
例如:
@property(nonatomic , assign)NSString *name;
- (void)setName:(NSString *)name
{
_name = name;
}
-(NSString *)name{
return _name;
}
如果语义设置的关键字是retain,setter、getter的内部实现会做内存优化
例如:
@property(nonatomic,retain)NSString *name;
- (void)setName:(NSString *)name{
if(_name != name){
[_name release];
_name = [name retain];
}
}
- (NSString *)name{
return [[_name retain]autorelease];
}
如果语义设置的关键字是copy,setter、getter的内部实现也会做内存优化
例如
@porperty(nonatomic , copy)NSString *name;
- (void)setName:(NSString*)name
{
if(_name!= name) {
[_name release];
_name= [name retain];
}
}
- (NSString*)name
{
return[[_name retain]autorelease];
}
4、特别注意
如果属性是非对象类型(比如int,float等)属性等语义设置只用assign
如果属性是对象类型(比如NSString,NSArray等)属性等语义设置使用retain
如果属性是对象类型,并且想得到参数的copy,使用copy关键字
0x04 属性之禅
推荐按照下面的格式来定义属性
@property (nonatomic, readwrite, copy) NSString *name;
属性的参数应该按照下面的顺序排列: 原子性、读写、内存管理。 这样做你的属性更容易修改正确,并且更好阅读。
你必须使用nonatomic,除非特别需要的情况。在iOS中,atomic带来的锁特别影响性能。
属性可以存储一个代码块。为了让它存活到定义的块的结束,必须使用copy(block 最早在栈里面创建,使用copy让 block 拷贝到堆里面去)