Objective-c:属性

吕翰飞
2023-12-01

简介
属性(property)是Objective-C的一项特性,用于封装对象中的数据。Objective-C对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其中,“获取方法”(getter)用于读取变量值,而“设置方法”(setter)用于写入变量值。这个概念已经定型,并且经由“属性”这一特性而成为Objective-C 2.0 的一部分,开发者可以令编译器自动编写与属性相关的存取方法。此特性引入了一种新的“点语法”(dot syntax),使开发者可以更为容易地依照类对象来访问存放于其中的数据。
属性声明
语法格式:@property (参数1, 参数2...) 类型 名字;
#import <Foundation/Foundation.h>

@interface Person : NSObject

// 属性生命
// 关键字   参数1     参数2      类型      名字
@property (strong, nonatomic) NSString *name;

@end

Tips

1、属性声明中的参数,将会在后文详细讲解;

属性的声明,需声明在@interface和@end之间,全局变量的下方,与方法的声明类似。

在 iOS4.4 之前,我们需要用到另一个属性关键字@synthesize,他的意义在于,将一个属性与对应的全局变量合成,这个关键字在iOS4.4以后不必再写出,系统会自动添加,但是实例变量依旧可用;

@synthesize name = _name;

在 iOS4.4 以后,使用前面的方法声明了一个属性即可直接使用,但是我们依然需要了解一个属性的完整诞生过程,它能帮我们更好的使用属性;

声明一个属性本质上就是指定一个set和取值方法,所以像前面提到的那些set和取值,都不写出,但是方法依旧可用。

iOS5之前和iOS5之后,属性在定义形式上做了一定的简化,不重写setter()和getter()方法时,也可不使用@synthesize 关键字,且成员变量不必写出,也能自动生成一个带下划线的同名成员变量;

iOS5之前,书写属性的步骤:

1) 先写出带下划线的成员变量;如 NSString * _name;

2) 使用@property 配备一个不带下划线,且与成员变量同名的属性;

@property(nonatomic , retain) NSString * name;

3)使用关键字@synthesize将成员变量和属性名进行合成;

@synthesize name = _name;

属性关键字
@property后面的()内可以配置一些参数,配置了参数后,编译器会为我们生成不同的getter和setter方法,下面我们来看看有哪些可配置的参数:

读写属性
读写属性即控制了属性是否存在设置器方法,这些参数之间是互斥的。

readwrite(默认): 表名了属性是可读可写的,即属性具有setter方法和getter方法,若该属性由@synthesize实现,则编译器会自动生成这两个方法;

readonly:表明属性是只读的,即属性只有获取器方法,将生成getter方法而不生成setter方法。如果视图对该属性使用点语法赋值,将引起编译器错误,只有当该属性由@synthesize实现时,编译器才会为其合成获取方法;

原子性
automic(默认):这个属性是为了保证程序在多线程情况,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题;

nonatomic:该属性不提供多线程保护,如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率;

内存管理语义
属性用于封装数据,而数据则要有“具体的所有权语义”。下面这一组特质仅会影响“设置方法”。例如,用“设置方法”设定一个新值时,它应该是“保留(retain)”此值呢,还是只将其赋给底层实例变量就好?编译器在合成存取方法时,要根据此特质来决定所生成的代码。如果自己编写存取方法,那么久必须同有相关属性所具备的特质相符。

retain:对象使用,持有对象,retainCount + 1;

assion:这个属性一般用来处理基础类型,比如int、float等待,如果你声明的属性是基础类型的话,assign是默认的,你可以不加这个属性;

strong:此特质表明该属性定义了一种“拥有关系”。为这种属性设置新值时,设置方法会先保留新值,释放旧值,然后再将新值设置上去。主要用于修饰强引用的属性;

weak:此特质表明该属性定义了一种“非拥有关系”。为这种属性设置新值时,设置方法既不保留新值,也不释放旧值。此特质同assin类似,然而在属性所指的对象遭到摧毁时,属性值也会清空。主要用于修饰弱引用的属性,当弱引用的对象被释放后,该对象将被自动赋予nil值;

copy:此特质所表达的所属关系与strong类似。然而设置方法并不保留新值,而是将其“拷贝”。当属性类型为NSString*时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个NSMutableString类的实例。这个类是NSString的子类,表示一种可以修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变”的字符串,确保对象中的字符串值不会无意间变动,只要实现属性所用的对象是“可变的”,就应该在设置新属性时拷贝一份。我们可以暂时这样理解,当它使用在不可变类型的属性时,等于strong;当它使用在可变类型时,每次赋值都会拷贝一个新的对象。

unsafe_unretained:此特质语义和assin相同,但是它适合用于“对象类型”,该特质表达一种“非拥有关系”,当目标对象遭到摧毁时,属性值不会自动清空(置为nil),这一点与weak有区别。

方法名
可通过如下特质来制定存取方法的方法名:

getter=< name >:指定“获取方法”的方法名。如果某属性时Boolean型,而你想为其获取方法加上is前缀,那么就可以用这个方法来指定。比如说,在登陆界面,表示登陆状态的属性就是这样定义的:
@property (nonatomic, assign, getter=isLogin) BOOL login;
1
setter=< name >:指定“设置方法”的方法名,这种用法不太常见,用法与getter=<name>一致;
Tips

1、一般情况下,只要是对象类型,都使用strong(后面可能有例外);

2、只要是非对象类型,都使用assign;

3、ARC模式下

weak 相当于 assign 相当于,但不等价,注意;

strong 相当于 retain 相当于;

点语法
点语法简介
有了属性,我们就可以使用另外一个语法:点语法。使用方法如下:

person.name = @"Admin";       // 设置器方法

NSString *name = person.name; // 访问器方法

Tips

1、第一个左边部分相当于一个设置器方法;

2、第二个右边部分相当于一个访问器方法;

3、点语法是objective-C 2.0 的新特性。一般声明完属性之后才能使用点语法;

点语法有点
方便程序员能够很快地转到OC上来;

让程序设计简单化;

隐藏了内存管理细节;

隐藏了多线程、同步、加锁细节;

点语法缺点
性能有点差,内部转化为setter,getter;

不易理解苹果的调用机制;

补充
在dealloc方法中,我们可以采用一种高明的技巧;

self.name = nil;

// 这行代码表示使用nil参数调用setAge:方法。生成的访问器方法将自动释放以前的age对象,并使用nil值替代,这样可以使我们避免对已有释放内存的悬空引用问题。

 类似资料: