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. 通过DAC来连接SQL Server

    最早知道能够使用专用管理员连接.来连接到sql server.可是一直没有成功连接过.今天又看到这个,于是想再试试. 1.通过在ssms中的"连接到server对话框"中的serv ...

  2. java 加减乘除错误

    有次做一个for循环(1000次左右),做的事情也是很简单的事情,就是   Double testValue = (long类型 / 8 ) * long类型 的一些加减乘除操作, 但是总是出现一些数 ...

  3. Android APK反编译具体解释(附图)

    这段时间在学Android应用开发,在想既然是用Java开发的应该非常好反编译从而得到源码吧,google了一下,确实非常easy,下面是我的实践过程. 在此郑重声明,贴出来的目的不是为了去破解人家的 ...

  4. [Node.js] Node.js Buffers

    >> node >>fs.readFile('finnish.txt', function(err,data){ console.log(data); }); // Outpu ...

  5. Android保存设置的PreferenceActivity

    界面XML文件:preference_setting.xml <?xml version="1.0" encoding="UTF-8"?> < ...

  6. JavaBean中DAO设计模式介绍(转)

    一.信息系统的开发架构 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层就是客户端,简单的来说就是浏览器. 2.显示层:JSP/Ser ...

  7. java 使用线程做一个简单的ATM存取款实例.(转)

    线程 Thread 类,和 Runable 接口 比较两者的特点和应用领域. 可以,直接继承线程Thread类.该方法编写简单,可以直接操作线程,适用于单重继承情况,因而不能在继承其他类 实现Runn ...

  8. SecureCRT使用教程

    Secure CRT是一款支持 SSH2.SSH1.Telnet.Telnet/SSH.Relogin.Serial.TAPI.RAW 等协议的终端仿真程序,最吸引我的是,SecureCRT 支持标签 ...

  9. 异步DNS解析的实现

    在高性能爬虫为什么使用定制DNS客户端一文中阐述了DNS解析是网络爬虫的瓶颈. 目前主要有两种方法来提高DNS解析效率: 1. 基于多线程的DNS 解析 2. 基于NIO的DNS解析 dnsjava中 ...

  10. Java基础知识强化之集合框架笔记62:Map集合之HashMap嵌套HashMap

    1. HashMap嵌套HashMap  传智播客          jc    基础班                      陈玉楼  20                      高跃   ...