《Effective Objective-C 2.0》4、Objective-C类的属性

1、属性——property

Objective-C的属性用于封装对象之中的数据,其作用同类的数据成员类似,但是所起到的作用远远大于普通的数据成员。声明属性使用@property关键字,这样就可以快速方便地为实例变量创建存取器,并可以通过点语法使用使用存取器。获取属性的变量值使用getter方法,设置属性的变量值使用setter方法。

2、property的使用

使用属性的例子如下:

//
//  Vehicle.h
//

#import <Foundation/Foundation.h>

@interface Vehicle : NSObject

@property (nonatomic, copy) NSString *carName;
@property (nonatomic, copy) NSString *carType;

@end

//
//  Vehicle.m
//

#import "Vehicle.h"

@implementation Vehicle

@end
//
//  main.m
//

#import <Foundation/Foundation.h>
#import "Vehicle.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        Vehicle *obj1 = [[Vehicle alloc] init];
        obj1.carName = @"Ferrari";
        obj1.carType = @"SuperSportCar";
        NSLog(@"Car name is %@ and type is %@", obj1.carName, obj1.carType);

        Vehicle *obj2 = [[Vehicle alloc] init];
        [obj2 setCarName:@"BMW X5"];
        [obj2 setCarType:@"SUV"];
        NSLog(@"Car name is %@ and type is %@", obj2.carName, obj2.carType);
    }
    return 0;
}

@property等同于在头文件中声明了set和get方法,同时也自动在实现文件中使用synthesize实现了set和get方法。相对于自己手动声明数据和方法成员,使用属性可以大幅简化代码。

3、property的特性

在声明属性的时候,还需要制定一些关键字对属性进行修饰,如nonatomatic、copy等。一般用来修饰属性的特性关键字有三类:原子性、存取器控制和内存管理。

(1)、原子性:

  • atomic:使用该特性修饰的属性是线程互斥的,即最多只能有一个线程同时访问。该属性是默认的,只有在严格要求线程安全的场合下会使用。
  • nonatomic:使用该特性修饰的属性时线程非安全的,可以同时被多个线程访问。使用nonatomic的属性效率相对较高,在大多数场合使用的是这个特性。

(2)、存取器控制:

主要用于控制属性的set和get方法。

  • readwrite:默认属性,表示该属性同时支持读操作和写操作,同时具有setter和getter。
  • readonly:表示该属性只读,只有getter没有setter。

另外,还可以自定义setter和getter的函数名,如:

@property (nonatoic, setter = mySetter:, getter = myGetter) NSString *name;

(3)、内存管理

内存管理特性表明了该属性与保有它的对象之间的关系:

  • assign:默认属性,用于值关系。通常int、float等数值类型极其封装如NSInteger等属性,以及代理对象通常采用assign特性。
  • retain:父对象对属性对象拥有所有权,父对象建立后,属性对象的引用计数加1。只要父对象的引用存在,那么属性对象就不会被释放。对于大部分“类”类型的属性,应采用retain特性。
  • copy:与retain类似,父对象存在对属性对象的强引用,但是会在父对象建立时为属性对象建立一份拷贝副本,父对象引用的是这一个副本。使用最多的是NSString类型的属性。

在iOS加入了ARC后,属性的内存管理特性新增添了strong和weak两个:

  • strong:与retain相同,即父对象对属性对象强引用,属性对象的引用计数+1,属性对象不会在父对象生命周期结束之前被释放。
  • weak:类似于assign,即父对象对属性对象弱引用,属性对象的引用计数不增加,父对象也不能干涉属性对象生命周期,当属性对象在其他地方被释放之后,父对象的这个属性被设置为nil。
  • unsafe_unretain:该属性类似于assign,说明父对象不对属性对象存在强引用,但是与weak不同的是当属性对象被释放后,父对象的属性不会被设置为nil。

4、直接访问实例变量还是通过属性访问类成员

这两种访问方式有几个区别:

  • 直接访问类成员的速度较快,因为省略了Objective-C的“方法派发”,编译出来的代码会直接访问实例成员的内存。
  • 直接访问类成员,将绕过其setter和getter方法,那么属性声明时规定的特性将失效。
  • 直接访问类成员,不会触及KVO。

在对象外部访问对象的属性成员,总应该使用属性;在对象内部,应该尽量直接访问实例成员。另外,还需要遵循以下规定:

  1. 对象内部读取数据时直接访问,写入数据时通过属性来写入;
  2. 在init和dealloc方法中,始终直接访问实例变量;
  3. 在进行了惰性初始化时,通过属性来读取数据。
时间: 2024-09-20 00:32:20

《Effective Objective-C 2.0》4、Objective-C类的属性的相关文章

Eero 2011-07-20发布 二进制Objective C 2.0兼容变体

Eero 2011-07-20版本增加了一个新的"pass message" 操作符,由冒号表示.变更了信息链接的语法. 同时提升了":=" 操作符,并且支持对象的实体变量. Eero 是一个二进制兼容的 Objective C 2.0 的变体,其目的是为了让代码编写更加简单,提升代码的可读性.Eero 实现了补丁版的 Clang/LLVM 编译器.Eero 使用类 Python 的代码缩进以及操作符重载限制.该语言主要从 Smalltalk 和 http://ww

Eero 2011-09-01发布 二进制Objective C 2.0变体

Eero 2011-09-01是第一个beta版本的发布.引入新的嵌套函数,添加为NSRanges句法支持. Eero是一个二进制兼容的Objective C 2.0 的变体,实现了补丁版的Clang/LLVM编译器.其特点5649.html">是为了让代码编写更加简单,降低了代码的混乱,提升代码的可读性.Eero使用类Python的代码缩进以及操作符重载限制.该语言主要从Smalltalk 和 http://www.aliyun.com/zixun/aggregation/13430.h

Eero 2011-08-15发布 二进制Objective C 2.0变体

Eero 2011-08-15该版本方括号不再使用的消息传递.消息代码被重构. Eero 是一个二进制兼容的Objective C 2.0 的变体,实现了补丁版的Clang/LLVM编译器.其特点5649.html">是为了让代码编写更加简单,降低了代码的混乱,提升代码的可读性.Eero 使用类 Python 的代码缩进以及操作符重载限制.该语言主要从 Smalltalk 和 http://www.aliyun.com/zixun/aggregation/13430.html"&

Eero 2011-08-02发布 二进制Objective C 2.0 的变体

Eero 2011-08-02版本引入了Compact blocks. 详细信息:http://eerolanguage.org/ Eero 是一个二进制兼容的Objective C 2.0 的变体,实现了补丁版的Clang/LLVM编译器.其特点是为了让代码编写更加简单,降低了代码的混乱,提升代码的可读性.Eero 使用类 Python 的代码缩进以及操作符重载限制.该语言主要从 Smalltalk 和 Ruby 中获得灵感. 下载地址:http://eerolanguage.org/wp-c

Eero 2011-07-24发布 二进制Objective C 2.0变体

Eero 2011-07-24该版本强调数值文字是被充许的. Eero 是一个二进制兼容的 Objective C 2.0 的变体,其目的是为了让代码编写更加简单,提升代码的可读性.Eero 实现了补丁版的 Clang/LLVM 编译器.Eero 使用类 Python 的代码缩进以及操作符重载限制.该语言主要从 Smalltalk 和 http://www.aliyun.com/zixun/aggregation/13430.html">Ruby 中获得灵感. 下载地址:http://ee

Eero 2011-06-25发布 二进制兼容Objective C 2.0变种

Eero 是一个二进制兼容的 Objective C 2.0 的变种,其目的是为了让代码编写更加简单,提升代码的可读性.Eero 实现了补丁版的 Clang/LLVM 编译器.Eero 使用类 Python 的代码缩进以及操作符重载限制.该语言主要从 Smalltalk 和 http://www.aliyun.com/zixun/aggregation/13430.html">Ruby 中获得灵感. Eero 2011-06-25支持增加了对选择和协议"文本"对象和类转

ASP.NET2.0中的ClientScriptManager 类用法

asp.net|client ASP.NET2.0中的ClientScriptManager 类用法-如何添加客户端事件 在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能用在页中的来自不同用户控件的相似脚本. <html>  <head>    <title>ClientScriptManager Example<

ASP.NET 2.0中的ClientScriptManager类用法—如何添加客户端事件

在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能用在页中的来自不同用户控件的相似脚本. <html> <head> <title>ClientScriptManager Example</title> </head> <body> <form id="Form1&quo

ejb方法调用-EJB3.0中怎么一个类调用另外一个类的方法

问题描述 EJB3.0中怎么一个类调用另外一个类的方法 我做得的是struts+ejb3.0,在EJB中我想用BIZ调用dao,是直接New还是有别的方法...求大神指教..... 这是BIZ的方法 public List queryPet(String pelName,String pelZr,String pelType ,String px) { System.out.println("aaaaaaaaaaaaaaaaaaaa"); IDao dao=new IDaoImpl()

cas-CAS4.0 中UsernamePasswordCredentialsToPrincipalResolver这个类没有了

问题描述 CAS4.0 中UsernamePasswordCredentialsToPrincipalResolver这个类没有了 现在如果要返回更多用户信息怎么配置用户认证凭据转化的解析器原来是这样的 enter code here ` ` 解决方案 有principalresolver这个类,可以重写getperson这个方法来返回