首页 > 白话Objective-C > 白话Objective-C之Property

白话Objective-C之Property

面向对象三大要素之一的封装,永远是处于最基础最重要的一环。数据不仅被封装到对象的成员变量里面,苹果还通过property对数据进一步地封装。可谓是对数据的封装做了浓妆重彩的处理。

一、使用@property配合@synthesize可以让编译器自动实现getter/setter方法,官方推荐的做法:
1、成员变量采用下划线命名:NSString *_name
2、在h头文件写上property,比如@propery(readwrite,copy) NSString *name;相当于声明方法。当然也可以在m文件写property来声明一个私有属性
3、在m文件写上synthesize,@synthesize name = _name;相当于定义方法。

二、property的格式说明

1、property的格式如下:@property  (<parameters>) <type> <name>;
parameters可以从下面这三组关键字中取适当的值用逗号组合起来:nonatomatic|atomatic     readonly|readwrite  assign|retain|copy
parameters,默认的取值是atomic, readwrite, and assign
type:是变量的类型
name:是变量的名称

2、举例:
@propery(atomatic,readwrite,copy) NSString *name;
@property(readwrite,assign)BOOL isDone;

3、关于property参数的详细说明:

atomic:原子操作,用于多线程。多线程下,若一个写操作是分成多条cpu指令完成的的,必须加锁把这多步当成是一个原子操作,防止在未写完的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
nonatomic:非原子操作

readonly 表示这个属性是只读的,只生成getter方法的声明,不会生成setter方法的声明。
readwrite,表示这个属性是可读可写的,既生成getter方法的声明,又生成setter方法的声明。

assign: 调用getter时,返回属性。调用setter时,简单赋值,不更改retain count。
用于基础数据类型  int, float, double, char, NSInteger等
retain 调用getter时,返回属性。setter调用时,指向同一块内存, retain count加1。用于object类型,
copy  调用getter时,返回属性。调用 setter时,是重新分配一块内存将相同的内容复制给属性,用于object类型

4、如果成员变量是NSString *_name 并且@synthesize name = _name;  @property里面的assign, copy, retina,setter函数展开如下表所示:

c07d205644248b1b58b62406071fc9e8总结:assign是简单的赋值,retain 是指针拷贝,copy 是内容拷贝。

三、使用property的好处:

1、内存管理:setter里面会根据property的参数采用正确的内存管理方法来创建变量。而不需要我们手动去写代码来做这些事情。

2、语法糖,我们可以采用 object.name的方式来调用getter跟setter的方法

3、可以非常方便地生成getter跟setter

4、自定义getter跟setter,我们还可以自定义自己的getter跟setter。比如当商品打折扣的时候,我们可以自定义getter,并在getter里面将价格乘以一个折扣,那么将会应用到所有getter里面。

5、方便使用kvo,采用了property的方式对成员赋值,那么就会触发kvo,而不需要willChangeValueForKey跟didChangeValueForKey

四、注意的地方:

1、在64-bit平台下
只需要声明 @property ,objecitve c runtime会自动帮我们创建@synthesize name = _name同时创建instance variable _name;
这是苹果开发人员觉得一遍一遍地写成员变量,property, synthesize,会非常烦,而且占用太多的代码,而做的简化。无疑这个简化是非常nice的。

在32-bit平台下
我们需要同时声明instance variable,@property @synthesize
否则会报一些错误。比如:Synthesized property ‘name’ must either be named the same as a compatible ivar or must explicitly name an ivar。
比如:若写了property,而没有写synthesize,在调用 get跟set方法的时候,会找不到实现的方法,所以调用错误,出现类似下面的错误提示:unrecognized selector sent to instance 0x18f6c30

所以如果我们要同时兼容64-bit平台跟32-bit平台,我们必须按照最严格的声明方式,采用32-bit的声明方式。

2、如果我们声明了property(retain,readwrite)NSString *name。而且自己又只自定义了一个getter方法(或者setter方法),系统会报一个警告:Fix warning: cannot pair a synthesized setter/getter with a user defined setter/getter。因为property有默认值atomic。而对于我们定义的getter或者setting,系统并不知道是atomic还是nonatomic,所以认为是nonatomic,导致跟property默认值atomic不一致。设置property为property(nonatomic,retain,readwrite)NSString *name,解决掉这个警告。

3、retain必须是object type,否则编译器会报一个错误:Property with ‘retain(or strong)’ attribute must be of object type

参考资料:

http://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

(转载本站文章请注明出处 www.helloitworks.com ,请勿用于任何商业用途)

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.