@property & @synthesize 及相关属性作用探究
@property :
ios6 引入关键词.
@property name; 指示编译器自动生成 name 的 setter 和 getter 方法 :
- (nsstring *)name;
- (nsstring *)name {
return _name;
}
- (void)setname:(nsstring *)string;
- (void)setname:(nsstring *)string {
if (_name != string) {
[_name release];
_name = [string retain];
}
}
而 @synthesize name = _name; 则是先去访问同名变量 _name, 没有则定义变量 _name, 意味着先生成变量, 再生成变量的 setter 及 getter; 如果自己实现了 setter 及 getter 则系统不再实现;
如果使用的是 @synthesize name; 则系统会生成变量 name 而不会生成 _name, getter 及 setter 中所返回也会变为 name.
如果该 property 使用 getter/setter 关键字修饰的则会生成对应方法名, 返回值为 @synthesize 后变量名;
如果同时使用 getter 和 setter 关键字 且同时手动实现了 setter 和 getter, 则系统不会自动生成变量 _name, 必须使用@synthesize name = xxx 才会生成对应变量;
注 : 默认实现 @synthesize name = _name, _name 可以是任何你想要的变量名.
另 : 对于属性和变量的理解, 属性仅仅只表示 setter 和 getter, @property 修饰的属性仅仅只是 setter 和 getter 缩写, 方便使用 'self.' 调用, _name 才是真正的变量.
#import "viewcontroller.h" @interface viewcontroller () @property (nonatomic, copy) nsstring * name; @end @implementation viewcontroller @synthesize name = username; - (void)viewdidload { [super viewdidload]; self.name = @"1111"; nsstring * namestring = self.name; nsstring * usernamestring = username; nslog(@"namestring : %@ usernamestring : %@", namestring, usernamestring); // namestring : 1111 usernamestring : 1111 username = @"2222"; nslog(@"self.name : %@", self.name); // self.name : 2222 // nslog(@"%@", _name); // use of undeclared identifier '_name' } @end
@property 参数:
读写 :
readwrite (读写) / readonly (只读),
内存管理 :
assign : 默认类型, 对 setter 方法参数不进行 retain 操作, 适用于基本数据类型.
retain : 对 setter 变量旧值进行一次 release 操作, 对参数进行 retain 操作, 适用于对象.
copy : 暂且定义为作用同 retain (具体待深浅拷贝探究).
strong : 同 retain, arc 下使用.
weak : 作用同 assign, arc 下使用, 不同的是可以对对象使用, 对象释放时会将对象置位 nil.
并发性 :
nonatomic / atomic 区别 : 用来决定编译器在生成的 setter 和 getter 是否为原子操作. atomic 提供线程安全, 描述该变量是否支持多线程同步访问, 系统会自动创建 lock 锁锁定变量, 而 nonatomic 禁止多线程访问, 保护变量, 提高性能.
属性默认为 atomic, 为了避免多线程访问该变量, 造成读写的不同步, 编译器会自动生成一些互斥加锁代码, 会损耗性能.
nonatomic : 如果属性无需考虑多线程的情况, 则可以使用该属性, 禁止多线程访问, 提高性能.
atomic : 系统自动生成 setter/getter, 手动生成 setter 和 getter 会警报不能配对.
#import "viewcontroller.h" @interface viewcontroller () @property (atomic, copy) nsstring * name; @end @implementation viewcontroller - (void)viewdidload { __weak typeof(self) weakself = self; dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ self.name = @"1111"; }); dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ self.name = @"2222"; }); // 两秒后打印值 dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(6 * nsec_per_sec)), dispatch_get_main_queue(), ^{ nslog(@"%@", weakself.name); }); } - (void)setname:(nsstring *)name { // writable atomic property 'name' cannot pair a synthesized getter with a user defined setter _name = name; } @end
nonatomic : 两个线程访问 setter, 两个线程访问 getter, 如下: 两次打印结果不定, 可能是 (@"222", @"222") 也可能是 (@"11111", @"11111"), 还可能是 (@"2222", @"11111").
所以说 nonatomic 在多线程情况下会出现问题, 如果是多线程还需进一步处理. ☆☆☆☆☆ -- 怎么处理???
#import "viewcontroller.h" @interface viewcontroller () @property (nonatomic, copy) nsstring * name; @end @implementation viewcontroller - (void)viewdidload { __weak typeof(self) weakself = self; dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ weakself.name = @"2222"; }); dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ nslog(@"%@", weakself.name); }); dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ weakself.name = @"11111"; }); dispatch_async(dispatch_queue_create(nil, dispatch_queue_concurrent), ^{ nslog(@"%@", weakself.name); }); } - (void)setname:(nsstring *)name { _name = name; } @end
atomic 示例 :
{lock} if (property != newvalue) { [property release]; property = [newvalue retain]; } {unlock}
用atomic会在多线程的设值取值时加锁,中间的执行层是处于被保护的一种状态,atomic是oc使用的一种线程保护技术,基本上来讲,就是防止在写入未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iphone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
引用参考 : http://www.cnblogs.com/rong-shengcom/
下一篇: 乐侃生活的幽默逗段