@property & @synthesize & @dynamic 及相关属性作用探究
@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 才是真正的变量, 是由系统 @synthesize 生成.
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, copy) NSString * name;
@end
@implementation ViewController
@synthesize name = userName;
- (void)viewDidLoad {
[super viewDidLoad];
self.name = @"";
NSString * nameString = self.name;
NSLog(@"nameString : %@ userName : %@", nameString, userName); // nameString : 1111 userName : 1111
userName = @"";
NSLog(@"self.name : %@", self.name); // self.name : 2222
// NSLog(@"%@", _name); // 因为使用 @synthesize name = userName;所以报错 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 = @"";
});
dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{
self.name = @"";
});
// 两秒后打印值
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * 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 在多线程情况下会出现问题, 如果是多线程还需进一步处理. ☆☆☆☆☆ -- 怎么处理, 使用 atomic ???
#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 = @"";
});
dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{
NSLog(@"%@", weakself.name);
});
dispatch_async(dispatch_queue_create(nil, DISPATCH_QUEUE_CONCURRENT), ^{
weakself.name = @"";
});
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/
补充
@dynamic: 同样是 @property 对应的关键字, 该关键字需要手动编写, 它会告诉编译器, @property 修饰的属性所对应的 getter 和 setter 是动态绑定, 由用户自己实现, 不需要自动实现, 若该属性是由 readonly 修饰, 则只需要实现一个 getter 即可. 注: 如果属性声明为 dynamic, 且用户没有实现该属性对应的 getter 和 setter, 编译时没有问题, 在用户调用属性的 getter 或 setter 的时候, 就会崩溃,报错 'unrecognized selector sent to instance', 编译时由于是@dynamic, 所以编译器不会报错, 运行时执行对应方法, 即动态绑定.
@property & @synthesize & @dynamic 及相关属性作用探究的更多相关文章
- IOS 关键字self,super,copy, retain, assign , readonly , readwrite, nonatomic、 @synthesize、@property、@dynamic
IOS 关键字self,super,copy, retain, assign , readonly , readwrite, nonatomic. @synth ...
- OC的特有语法-分类Category、 类的本质、description方法、SEL、NSLog输出增强、点语法、变量作用域、@property @synthesize关键字、Id、OC语言构造方法
一. 分类-Category 1. 基本用途:Category 分类是OC特有的语言,依赖于类. ➢ 如何在不改变原来类模型的前提下,给类扩充一些方法?有2种方式 ● 继承 ● 分类(Categor ...
- 依赖配置中心实现注有@ConfigurationProperties的bean相关属性刷新
配置中心是什么 配置中心,通过key=value的形式存储环境变量.配置中心的属性做了修改,项目中可以通过配置中心的依赖(sdk)立即感知到.需要做的就是如何在属性发生变化时,改变带有@Configu ...
- PyQt(Python+Qt)入门:Designer组件属性编辑界面中QWidget类相关属性详解
本文适用人员:本文比较长,适合不理解Qt Designer部件属性的人员阅读或资料查找. 声明: 1.如果有人认为本文是简单的复制粘贴+翻译而成,敬请读本文最后的后记: 2.本文为老猿Python学习 ...
- Activity Intent Flags及Task相关属性
转自http://www.cnblogs.com/lwbqqyumidi/p/3775479.html 今天我们来讲一下Activity的task相关内容. 上次我们讲到Activity的四种启动模式 ...
- Android总结篇系列:Activity Intent Flags及Task相关属性
同上文一样,本文主要引用自网上现有博文,并加上一些自己的理解,在此感谢原作者. 原文地址: http://blog.csdn.net/liuhe688/article/details/6761337 ...
- UILabel的相关属性设置
在iOS编程中UILabel是一个常用的控件,下面分享一下UILabel的相关属性设置的方法. 很多学习iOS6编程都是从storyboard开始,用到UILabel时是将控件拖到storyboard ...
- css margin的相关属性,问题及应用
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=48 引言:margin ...
- List的方法和属性 方法或属性 作用
List的方法和属性 方法或属性 作用 Capacity 用于获取或设置List可容纳元素的数量.当数量超过容量时,这个值会自动增长.您可以设置这个值以减少容量,也可以调用trin()方法来减少容量以 ...
随机推荐
- JS 计算时间差,(引入外部字体文件)
JavaScript Date() 对象: new Date() :时间对象,会把当前时间作为其初始值: setFullYear() :用于设置月份,可有三个参数,setFullYear(year,m ...
- Android 显示html标签或者带图片
Android中显示html文件要用Html.fromHtml(...)处理过的返回值,返回值可以成为setText()的参数. 只显示带文本的html可以用下面的方法处理html文件. public ...
- Android碎笔录3——点击跳转
只要是view都能设置点击事件,不必要非得是Button. 要想实现跳转得三步走: 第一步.绑定 每个Layout都有一个一个java文件跟它绑定,这个Layout相关的代码都写在这个java文件里 ...
- Java基础之StringBuffer和StringBuilder的区别
StringBuffer是一个字符串的缓存类,属于一个容器,对于容器,我们可以进行增删改查. StringBuffer的容器长度是可变的,并且里面可以存放多种的数据类型.它跟其他容器,比如数组,是很不 ...
- [翻译] ABPadLockScreen
ABPadLockScreen ABPadLockScreen aims to provide a universal solution to providing a secure keypad/pi ...
- Python学习---网络编程 1217【all】
OSI七层模型: 物理层, 数据链路层, 网络层,传输层,会话层,表达层,应用层 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 传输层:TCP,UDP 网络层:I ...
- Skype for Business 安装组件RewriteModule失败
最近QQ网友提到部署Skype for Business,安装组件时提示安装必备组件失败:RewriteModule,如下图,安装文件名是rewrite_2.0_rtw_x64.msi,尝试手动安装也 ...
- 秒杀场景下MySQL的低效(转)
秒杀场景下MySQL的低效 2016-01-14 17:12 178人阅读 评论(0) 收藏 举报 最近业务试水电商,接了一个秒杀的活.之前经常看到淘宝的同行们讨论秒杀,讨论电商,这次终于轮到我们自己 ...
- angularjs中factory, service和provider
在Angular里面,services作为单例对象在需要到的时候被创建,只有在应用生命周期结束的时候(关闭浏览器)才会被清除.而controllers在不需要的时候就会被销毁了(因为service的底 ...
- 原生js模仿jq fadeIn fadeOut效果 兼容IE低版本
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...