OC属性
[toc]
属性的作用
1. 为成员变量提供访问的接口。setter和 getter 方法
@property 与 @synthsize 搭配使用,当你没有实现属性的setter和 getter方法时,系统会默认帮助生成Setter getter。
-
@synthSize var = _var;
如果没有生成set、get方法,则默认帮助生成访问器方法。在iOS4.4以前需要搭配@property使用,4.4以后@property不需要显示声明@synthsize即可生成访问器方法。
-
@dynamic var;
声明dynamic以后将由程序员自己生成set/get方法,并且如果没有实现不会触发警告,如果真没有实现而又调用了该属性,则会导致crash
2. 属性修饰符
-
nonatomic/atomic
- nonatomic
- 线程不安全 多个线程可以同时对其进行访问,没有资源保护
- 访问速度快
- atomic
- 线程安全 在多线程中只能有一个线程对进行访问,会默认会setter方法加锁(MRC环境重写Setter方法需要设置访问锁)
- 访问效率慢
- nonatomic
-
assign/weak
- assign
- 修饰基本数据类型(非指针型变量)setter方法里不会进行任何retain操作
- assign如果拿来修饰对象类型会有野指针(悬垂指针)的危险。(MRC使用unsafe_unretained修饰对象类型).assign修饰对象的话,如果对象释放了不会置为nil|
- weak
- 修饰对象类型。Arc下使用 和assign的效果一致
- weak比assign优化的一点是,当对象释放了以后可以将修饰的指针置为nil,可以有效避免野指针的行为
- assign
-
copy / Strong / Retain
讨论copy 需要补充一下 深拷贝|浅拷贝 的知识
// 结论
// 1.容器类型的指针 copy 只会产生不可变对象, mutableCopy 只会产生可变对象 与指针本身可变性无关
// 2.容器类型的指针 copy/mutableCopy 只是对数组内部元素指针的复制,不会去调用元素的copy方法,所以copy后新容器内部的元素内容是不变的。
- copy
// 系统引用计数的默认实现
- (void)setName:(NSString *)newname {
if (_name != newname) {
[_name release];
_name = [newname copy];
}
}
由上可以看出:
1. copy 修饰符 会先对旧对象release,然后copy一份新对象。因此会对引用计数进行+1
2. copy 修饰符的特点就是会对对象进行一次copy。
- strong
// 系统引用计数的默认实现
- (void)setName:(NSString *)newname {
if (_name != newname) {
[_name release];
_name = [newname retain];
}
}
由上可以看出: **strong 修饰符 会先对旧对象release,然后赋值并对新对象reatin。也会对引用计数进行+1**
- retain
retain 是MRC时代的产物,retain的实现和strong是一样的,因此strong 也可以用于MRC下。
特别注意:对于NSArray,NSDictionary,NSString这样的不可变对象我们需要使用copy来修饰,如果使用了strong,则对象被赋值了一个可变对象的时候,不可变对象的内容就可以发生改变了.容易造成语义的矛盾,也极有影响代码的运行。
-
readonly/readwrite
readwrite就是可读写,不加这个属性修饰符默认就是如此,所有变量都是可以读写的,也就是都自带setter和getter方法,而使用readonly修饰系统会自动生成getter方法而不生成setter方法所以是只读的,无法赋值。
3.另外一些标示符
-
const
NSString const *str = @"123"; NSString * const str1 = @"123"; str = @"456"; // 这句话只是把456的内存地址分配给str str 本身是一个变量,但它指向的内存是不可变的 str1 本身是一个常量,*str1 是一个变量
const 相比 宏定义define:
1. const 在编译阶段参与编译,宏则是在预编译阶段 2. 宏不做类型检查,只是替换内容,const 会编译检查类型 3. 宏可以定义函数方法代码块,const不行
-
static
static 修饰的变量都是在字符常量区- static 修饰全部变量
- 限制了全局变量的作用域为当前文件内
- static 修饰局部变量
- 让局部变量只初始化一次
- 局部变量在程序中只有一份内存
- 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期
- static 修饰全部变量
-
extern
对extern来说,可以理解为扩展吧,将当前变量的作用域从一个类扩展到另一个类。