http://my.oschina.net/u/728866/blog/90798


property,可以提供的功能有:提供成员变量的访问方法的声明、控制成员变量的访问权限、控制多线程时成员变量的访问环境 )。

property不但可以在interface,在协议protocol .和类别category中也可以使用.

synthesize的理解是:实现property所声明的方法的定义。

其实说直白就像是:property声明了一些成员变量的访问方法 ,synthesize则定义了由property声明的方法。他们之前的对应关系是

property 声明方法 ----------》 头文件(.h)中申明的方法

synthesize定义方法---------》Cpp文件(.m)中定义的方法

不过这里还有有一点细微的差别,后面我会讲到。


先讲property

大家都知道:@property(attribute1 , attribute2, ...])是@property的他的官方表达方式,所以看到attribute1, attribute2,你就应该懂的, 他的用法不是很简单。下面就对他的属性列表进行分类介绍:

下面对属性列表进行一下简单的介绍,后续会用代码来解释。

1.可读性:readonly 、readwrite

@property(readwrite,....) valueType value;

这个属性是变量的默认属性,就是如果你(readwrite and readonly都没有使用,那么你的变量就是readwrite属性),通过加入readwrite属性你的变量就会有get方法,和set方法。

property(readonly,...) valueType value;

这个属性变量就是表明变量只有可读方法,也就是说,你只能使用它的get方法。

2,assign,setter方法直接赋值,不进行任何retain操作,为了解决原类型与环循引用问题对基础数据类型 。

3,retain,setter方法对参数进行release旧值再retain新值,所有实现都是这个顺序

4,copy,setter方法进行Copy操作,与retain处理流程一样,先旧值release,再Copy出新的对象,retainCount为1。这是为了减少对上下文的依赖而引入的机制。

5  相对原文进行了修改,更便于理解.

a ) atomic的意思就是setter/getter这个函数是一个原语操作。当设置了多线程操作时,如果有两个以上线程同时调用setter的话,不会出现某一个线程执行setter全部语句之前,另一个线程开始执行setter情况,相当于函数头尾加了锁,以保证多个线程取到的东西的一致性.
b ) nonatomic不保证setter/getter的原语行,所以多线程调用时可能取到东西并不一致,比如setter函数里面改变两个成员变量,如果你用nonatomic的话,getter可能会取到只更改了其中一个变量时候的状态,这样取到的东西会有问题。

如果不需要多线程支持的话,当然nonatomic就够用了,另外由于不涉及锁操作,所以它执行相对快点.

注意,如果不加此属性,则默认是两个访问方法都为原子型事务访问。锁被加到所属对象实例级.

所以 不加nonatomic对与多线程是安全的 。


其实他们都可以用代码表示:

1.nonatomic 和 atomic

@property(nonatomic ) NSObject* test1;

@synthesize test1;

上面两句代码,表示我们对test1的访问,是非多线程安全的。

@property(atomic) NSObject* test1;

@synthesize test1;

上面两句代码,表示我们对test1的访问,是多线程安全的。其实也就是在讲该成员变量放到互斥代码中,例如,下面进行加锁。

[_internal lock]; // lock using an object-level lock 
id result = [[value retain] autorelease]; 
[_internal unlock]; 
return result;

就如上面所说 ,这两个属性,是出于对多线程条件下 ,对test1的访问安全。如果你的程序的成员变量不存在安全问题,用nonatomic 就好,因为这样不要在访问是进行互斥,效率更高。

2. readonly 、readwrite (注,后续过程我们都会加入nonatomic 属性,因为它是十分普遍的)

2.1 readonly 

@property(nonatomic  ,readonly) NSObject* test1;

@synthesize test1;

上面的两句代码,objc编辑器将会为我们翻译为:

@property(nonatomic  ,readonly) NSObject* test1; 等同

-(NSObject*)test1;

@synthesize test1;等同

-(NSObject*)test1

{

return test1;

}

2.2 readwrite 

@property(nonatomic  ,readwrite ) NSObject* test1;

@synthesize test1;

上面的两句代码,objc编辑器将会为我们翻译为:

@property(nonatomic  ,readwrite ) NSObject* test1; 等同

-(NSObject*)test1;

-(void)settest1(NSObject* other);

@synthesize test1;等同

-(NSObject*)test1

{

return test1;

}

-(void)settest1(NSObject* other);

{

test1 = other;

}

这里要说明一下, readonly 、readwrite 这两个属性他们的真正价值,不是提供成员变量访问接口,而是控制

成员变量的访问权限。所以要抓住他们真正价值。

3. assign

@property(nonatomic  ,assign) NSObject* test1;

@synthesize test1;

上面两句:objc编辑器将会翻译如下:

@property(nonatomic  ,assign) NSObject* test1;等同

-(void)settest1(NSObject* other);

@synthesize test1;

-(void)settest1(NSObject* other);等同

{

test1 = other;

}

4. retain

@property(nonatomic  ,retain) NSObject* test1;

@synthesize test1;

objc编辑器翻译如:

@property(nonatomic  ,retain) NSObject* test1;等同

-(NSObject*)test1;

-(void)settest1(NSObject* other);

@synthesize test1;

-(NSObject*)test1

{

return test1;

}

-(void)settest1(NSObject* other)

{

if (test1!= other)

{

[test1release];

test1= [otherretain];

}

}

5. copy

@property(nonatomic  ,copy) NSObject* test1;

@synthesize test1;

objc编辑器将翻译如:

@property(nonatomic  ,copy) NSObject* test1;

-(NSObject*)test1;

-(void)settest1(NSObject* other);

@synthesize test1;

-(NSObject*)test1

{

return test1;

}

-(void)settest1(NSObject* other);

{

if (test1!=other) { 
        [test1release]; 
        test1= [othercopy]; 
    }

}

对于Copy属性有一点要主要,被定义有copy属性的对象必须要符合NSCopying协议,并且你还必须实现了

-(id)copyWithZone:(NSZone*)zone该方法。

 

代码才是王道:都是一些简单代码用例

//为了更具有普遍性,我选择用自定义对象testObj

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//testObj .h

@interface testObj : NSObject<NSCopying>{
    
}
@end 
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//testObj .m

-(id)copyWithZone:(NSZone *)zone
{
    testObj* pObj = [[testObj allocWithZone:zone] init];
    return pObj;
}
@end

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//testApp是包含多个testObj 对象指针

//testApp .h
@interface testApp :
{
    testObj*  test1;
    testObj*  _test2;
}

@property(nonatomic , retain) NSObject* test1;
@property(nonatomic , copy) NSObject* test2;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//testApp.m

@synthesize test1;

@synthesize test2 = _test2;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

@synthesize test2 = _test2; //对这里要特别主要一下,这里可以看作是一种别名机制,这点和前面类比的C++头文件和Cpp文件不同。

例如对于setter函数,objc编辑器将会按如下方式翻译

如果是@synthesize _test2;

setter函数将是这种形式:

-(void)set_test2(NSObject*); //注意中间的下划线

写成@synthesize test = _test2;

setter函数将是这种形式:
 -(void)settest2(NSObject*);// _test2 被 test2替换了

可以看出这种别名机制,感觉是规范书写(其实更像是规范Objc的书写,大家可以看看官方文档中,成员变量都是前面带下滑线的(如_test2),所以才搞了这样一个别名规范代码中的书写)

//下面是一个功能函数,

-(void )test

{

test1 = [[testObj alloc]init];// test1  retainCount  =1;

//下面有三种对test2操作方法:

_test2 = test1; //这里是将test1的指针赋值给_test2指针,注意,并没有调用test2的setter方法 ,所以test retainCount  = 1、 test2 retainCount  = 0;

self.test2 = test1; //这里调用test2的Copy方法,因此这是test retainCount  = 1、 test2 retainCount  = 1;

test2   = test1;

//这段代码系统将会提示出错说test2没有定义。因为这里编译器认为是一条赋值表达式,将test2看作是一个成员变量,而在我们的testApp 中是没有这个成员变量的,这里要区别我们所说的别名,别名机制可以看作是在调用setter或者getter函数才会起作用,而这里只是一个简单的赋值, 也就出现未定义的错误。如果没有理解,你就记住要调用setter或者getter函数,就用"self.成员变量"这种形式就行了.

//我们把  test2   = test1这行代码注释掉,保证程序继续执行

[test1 release];  // 释放test1 ,test1 retainCount  = 0;
    
    [test2 release]; // 释放test2 ,test2 retainCount  = 0;

}

@end

objective-C: nonatomic retain copy assgin 等属性详解的更多相关文章

  1. Linux文件权限与属性详解 之 ACL

    Linux文件权限与属性详解 之 一般权限 Linux文件权限与属性详解 之 ACL Linux文件权限与属性详解 之 SUID.SGID & SBIT Linux文件权限与属性详解 之 ch ...

  2. android:exported 属性详解

    属性详解 标签: android 2015-06-11 17:47 27940人阅读 评论(7) 收藏 举报 分类: Android(95) 项目点滴(25) 昨天在用360扫描应用漏洞时,扫描结果, ...

  3. OutputCache属性详解(一)一Duration、VaryByParam

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  4. OutputCache属性详解(二)一 Location

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  5. OutputCache属性详解(三)— VaryByHeader,VaryByCustom

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  6. OutputCache属性详解(四)— SqlDependency

    目录 OutputCache概念学习 OutputCache属性详解(一) OutputCache属性详解(二) OutputCache属性详解(三) OutputCache属性详解(四)— SqlD ...

  7. WPF依赖属性详解

    WPF依赖属性详解 WPF 依赖属性 英文译为 Dependency Properties,是WPF引入的一种新类型的属性,在WPF中有着极为广泛的应用,在WPF中对于WPF Dependency P ...

  8. HTML video 视频标签全属性详解

    HTML 5 video 视频标签全属性详解   现在如果要在页面中使用video标签,需要考虑三种情况,支持Ogg Theora或者VP8(如果这玩意儿没出事的话)的(Opera.Mozilla.C ...

  9. Android组件---四大布局的属性详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4372222.html Android常见布局有下面几种: LinearL ...

随机推荐

  1. cf 85 E. Petya and Spiders

    http://codeforces.com/contest/112/problem/E 轮廓线dp.每一个格子中的蜘蛛选一个去向.终于,使每一个蜘蛛都有一个去向,同一时候保证有蜘蛛的格子最少.须要用4 ...

  2. (转载)SVN 提交操作缩写(A D M R) .

    前言: 今天使用SVN提交代码,发现提交后的代码找不到之前的版本. 操作的字母缩写为R.一般我们常见的操作为 A D M R   A:add,新增 C:conflict,冲突 D:delete,删除 ...

  3. NodeJs读取源代码使用的字符集

    今天用NodeJs写了个简单的客户端/服务器程序,并让客户端向服务器发送汉字.当在Windows上执行客户端时,发现服务器端打印的接收到的数据是乱码.后来发现Windows上的客户端文件的储存编码方案 ...

  4. Android(java)学习笔记189:eclipse 导入项目是提示:某些项目因位于工作空间目录中而被隐藏。

    导致这个错误的原因是工程重名了: 并不是仅仅指文件夹重名,相信很多人也曾经修改过文件夹的名称,可惜没什么用处,关键是修改工程里面的一个文件!也就是.project这个文件! 用记事本打开,修改一下&l ...

  5. linux下安装apache2.2.27

    1.首先下载httpd-2.2.27.tar.gz用linux命令下载 wget http://mirrors.cnnic.cn/apache//httpd/httpd-2.2.27.tar.gz 2 ...

  6. javascript通过字典思想操作数据

    作为一名前端程序猿,相对于后端操作数据的机会较少.然而,有些时候因为一些特殊的原因(如:需要构造成对应插件需要的数据格式,需要返回特定的数据格式等)而不得不对数据进行筛选.重构.相对于后端语言,我们没 ...

  7. 局域网之php项目IP访问共享

    局域网之php本地项目共享 该文章主要介绍本地php项目在局域网内的共享访问,主要体现为通过本地ip地址访问项目 做法如下: 1.更改本地盘host文件(winds目录为:C:\Windows\Sys ...

  8. PHP一个最简单的CMS内容管理系统

    博客是一般程序员的入手戏,写得好写不好,有没有兴趣,逻辑性够不够都从这个里面入手 我现在摒弃前台.重点讲解下如何开发一个简单的CMS系统所需要的步骤: 1.清楚流程 1--------登录后台 2-- ...

  9. Java-Hirbernate中文乱码问题

    当你从前台接收的值一直到Action 里面都没有乱码的时候,然而写入数据库的时候确实乱码的 这里有几个原因: 1.你的数据库字符编码指定出问题了 当你指定varchar类型的时候,字符集一定要指定成u ...

  10. Java-hibernate的映射文件

    Hibernate 需要知道怎样去加载(load)和存储(store)持久化类的对象.这正是 Hibernate 映 射文件发挥作用的地方.映射文件告诉 Hibernate 它应该访问数据库(data ...