@property属性关键字之类的问题已经是被大家讨论烂了的话题,没什么新的东西,不过确实测试iOS开发者基础的一个利器。这个概念的了解程度直接反映了开发者对iOS内存管理的理解,以及ARC/MRC等内容。这篇博文记录了我对这些关键字的理解。
@property和@synthesize
@property是Objective-C的关键词,与@synthesize配对使用,用来让编译器自动生成与数据成员同名的方法声明。@synthesize则是用来生成对应声明方法的实现。简单的使用方法如下:
@interface Example : NSObject
@property (___ , ___) NSArray *exaArray;
@end
@implementation Example
@synthesize exaArray;
@end
@property的本质就是ivar
+getter
+setter
,他们就是属性中的两大概念:实例变量ivar
和存取方法access method:getter + setter
。
Property作为Objective-C
的一项特性,主要的作用就在于封装对象中的数据。Objective-C
对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过存取方法来访问。其中,getter用于读取变量值,而setter用于写入变量值。这个概念已经定型,并且经由“属性”这一特性而成为 Objective-C 2.0 的一部分。并且根据OBJC严格的命名规范,属性的存取方法是可以由编译器自动生成的。
@property属性关键字
首先,property属性主要包括以下大类:
1.原子性和非原子性:atomic
和nonatomic
2.可读可写功能:readwrite
和readonly
3.内存管理功能:unsafe_unretained
、assign
、retain
、strong
、weak
和copy
4.方法名:getter=<name>
,setter=<name>
5.类变量:class
1.原子性和非原子性
atomic
:默认是有该属性的,这个属性是为了保证程序在多线程情况下,编译器会自动生成一些互斥加锁代码,避免该变量的读写不同步问题。也就是说,同一时间内,属性的setter方法无法被两个线程调用,防止内存泄漏.
nonatomic
:如果该对象无需考虑多线程的情况,请加入这个属性,这样会让编译器少生成一些互斥加锁代码,可以提高效率。
2.可读可写功能
这两个关键字所代表的内容比较简单:使用readwrite
关键字,编译器会生成变量的setter和getter方法,访问者可以访问和改变变量的值,这个关键字也是默认的属性。而使用readonly
关键字编译器只生成变量的getter方法,访问者只能变量的值而不能改变它。
3.内存管理功能
assgin
:非ARC下变量的默认属性,只对变量进行简单的赋值,并未持有对象,不改变引用计数。适用于基础数据类。
retain
:release旧值,retain新值。就是说你需要对新的对象进行保持,而当指针指向新的对象后,旧的对象的引用计数-1。适用于NSObject类及其子类。
strong
:ARC下对retain属性的替代。只要某一对象被一个strong指针指向,该对象就不会被销毁。如果对象没有被任何strong指针指向,那么就会被销毁。在默认情况下,所有的实例变量和局部变量都是strong类型的指针。
而weak
属性则恰恰相反,当weak指针指向的对象没有被任何strong指针所指向,则weak指针被赋值为nil。weak和非ARC下的assgin相似,只不过多了在ARC下将指针赋值nil的功能。其实weak
和strong
的区别也就仅仅是是否决定对象的存亡。
copy
属性比较特殊,它是对对象的浅拷贝,并对拷贝后的对象强引用。以NSArray为例,当你对他使用copy关键字时,在内存中并不会重新开辟一个区域去存储,他的元素依然还是一样的,位置也不会变。copy
这里有一个坑就是当你对一个mutable变量使用copy关键字的话,实际上这个变量是一个不可变的,如果你对他进行修改的话会造成crash。例如:
@property (nonatomic, copy)NSMutableArray *array;
当你对上面的变量使用addObject:等语句时会造成程序crash。
4.方法名
这两个关键字很简单,普遍使用的是getter的那个方法。
@property (nonatomic, getter=isOn) BOOL on;
setter的方法名关键字不常用,也不推荐使用。
5.类变量
这个关键字大家会比较陌生,因为他是苹果在Xcode8中新加入的关键字,相当于Swift中的static,声明的是一个类(静态)变量,即所有这个类的对象共有的变量。有了这个我们就可以像Swift那样很easy的就实现一个单例。
Swift中单例模式这样写
class Singleton {
static let singleton:Singleton? = Singleton()
}
有了class关键字,Objective-C中单例可以这样写
@interface Singleton : NSObject :
@property (nonatomic, class, readonly) Singleton *singleton;
@end
@implementation Singleton
+(Singleton *) singleton {
Singleton *singleton = [[Singleton alloc] init];
return singleton;
}
@end
这个写法只是根据Swift写法的模仿,Xcode并不会报错。但是实际效果如何有待验证,这里只提供思路。
这篇文章是我的第一篇博文,包括了我自己的理解和我认为正确解读的总结。也不一定就是全面的,也会有一些理解不到位或者不对的地方,若有不同意见欢迎留言,我会一一回复。
网友评论