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. 笔记本PS/2键盘无法使用,试下这个方法

    用360清理了一下系统,再开机键盘就不灵了,鼠标却可以用. 打开设备管理器,看到PS/2标准键盘有个黄色的感叹号. 属性显示PS/2 标准键盘 Windows 无法加载这个硬件的设备驱动程序.驱动程序 ...

  2. AndroidUI组件之ActionBar--基于下拉的导航方式

      在上一篇关于ActionBar的博文中.我们知道了ActionBar是Android3.0的重要更新之中的一个.本篇博文就来写一个开发中经经常使用到的样例.用ActionBar提供基于下拉的导航方 ...

  3. richTextBox插入表格

    附件:http://files.cnblogs.com/xe2011/richTextBox_InsertTable.rar 插入表格 /// <summary> /// 插入表格 /// ...

  4. 【web开发学习笔记】ibatis学习总结

    ibatis学习总结 ibatis数据库配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCT ...

  5. Android 中 更新视图的函数ondraw() 和dispatchdraw()的区别

    绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现 绘制自己的孩子通过dispatchDraw(canvas)实现 View组件的绘制会调用draw(Canvas canv ...

  6. 统计中的PV,UV是的意思(转)

    PV(访问量):即Page View, 即页面浏览量或点击量,用户每次刷新即被计算一次. UV(独立访客):即Unique Visitor,访问您网站的一台电脑客户端为一个访客.00:00-24:00 ...

  7. 本地nginx多域名映射

    前言: 工作两年多了,一直感觉技术上没有太大的长进,好多东西感觉会但是给别人讲起来的时候又感觉和没学过一样.以后希望能坚持写博客,把看过的东西都一点一滴积累下来.言归正传,今天要说的是nginx与ho ...

  8. MFC/VC++ 响应回车键的实现

    在VC++中,要实现对回车键的响应实现,一般通过截获消息来响应,即通过处理BOOL PreTranslateMessage(MSG* pMsg)这个函数来处理 实现如下: BOOL PreTransl ...

  9. [转]cookie、session、sessionid 与jsessionid

    cookie.session.sessionid 与jsessionid,要想明白他们之间的关系,下面来看个有趣的场景来帮你理解. 我们都知道银行,银行的收柜台每天要接待客户存款/取款业务,可以有几种 ...

  10. AndroidStudio怎么将开源项目发布到jcenter

    前言 自己在网上搜了一大堆,大体就两种方法,而我选择的是其中代码少的的方法,不过他们或多或少留下了少许的坑,(按他们的方法我是上传成功,但不能发布到jCenter上去,也可能是我自己的问题o(≧v≦) ...