一、@property的本质是什么?
@property就是在编译阶段由编译器自动帮我们生成ivar实例变量,getter方法,setter方法;
属性(property)有两个概念:ivar(实例变量)、存取方法(access method = getter + setter)。当声明一个属性(property)的时候编译器会自动生成相关的getter和setter方法,除此之外,编译器还要自动向类中添加成员变量(在属性名前面加上下划线以此作为实例变量的名字);
在一个新建的Student类中通过@property声明了一个name属性
@interface Student : NSObject
@property(nonatomic, copy)NSString *name;
//等于与以下写法
{
//ivar
NSString *_name;
}
// setter
- (void)setName:(NSString *)name;
// getter
- (NSString*)name;
@end
属性(property)还提供了一些特殊的关键字来进行声明,包括assign(vs copy),weak(vs strong), atomic(vs nonatomic),readwrite(vs readonly)等。
二、@synthesize 和 @dynamic有什么作用?
@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果两个都没写,系统默认@synthesize var = _var;
@synthesize表示为属性自动生成相关的getter方法和setter方法;如:
@synthesize name = _name或@synthesize name
@dynamic告诉编译器属性的getter方法和setter方法由用户自己实现,不自动生成。如果没有提供相应方法,当程序运行到instance.var = someVar时由于缺少setter方法会导致程序崩溃;或者当运行到someVar = var时,由于缺少getter方法同样会崩溃。
@dynamic name;
//当使用@dynamic时,可以通过在.h文件中声明私有变量来实现
{
@private
__strong NSString *_name;
}
三、由于有了自动合成属性实例变量,@synthesize还有哪些使用场景?
首先应该清楚什么情况下不会自动合成实例变量:
- 同时重写了setter和getter时
- 重写了只读属性的getter时
- 使用了@dynamic时
- 在@protocol中定义的所有属性
- 在category中定义的所有属性
- 重载的属性
当你在子类中重载了父类的属性,你必须使用@synthesize来手动合成ivar。
四、property的指示符
- atomic(原子性)vs nonatomic(非原子性)
这主要是针对于多线程编程环境下来说的,当多线程访问同一块资源的时候,很容易引发数据错落和数据安全问题;
atomic(原子性)是默认的,在多线程下编译器会自动生成自旋锁代码,避免该变量的读写不同步问题,提供多线程安全,即多线程中只能有一个线程对它进行访问,中间不能被中断,当上一线程没有执行完毕的时候,下一个线程会一直等待(不会进入睡眠状态),因此会消耗大量资源,执行效率低。
nonatomic(非原子性),多个线程可以同时对其进行访问,不进行加锁,效率和性能较高,比较常用。 - readwrite(读写) vs readonly(只读)
readwrite是编译器的默认选项,表示自动生成getter和setter;
readonly表示只生成getter而不生成setter。 - strong(强引用) vs weak(弱引用) vs assign(赋值) vs copy(复制)
strong表示属性对所赋的值持有强引用表示一种“拥有关系”,会先保留新值然后释放旧值,只能修饰OC对象。
weak表示单纯引用某个对象,对新值不对改变引用计数。所赋的值在引用计数为0被销毁后,weak修饰的属性会被自动置为nil,能够有效防止野指针。weak常用在修饰delegate等防止循环引用的场景。UI控件之所以可以使用弱指针,是因为控制器有强指针指向UIView,UIView 有强指针指向Subviews数组,数组中由强指针指向控件。
copy是为了减少对上下文的依赖而引入的机制,内容被拷贝后,会在两个不同的内存空间存储内容,指针指向不同的内存地址。copy还被用来修饰block。
对于可变对象类型,如NSMutableString、NSMutableArray、NSMutableDictionary用strong修饰,因为strong是强引用,指向同一个内存地址,可以保证副本对象和源对象被修改。而NSString、NSArray、NSDictionary使用copy的目的是为了让本对象的属性不受外界影响。
参考:完整项目资料下载
网友评论