@property
默认格式:@syntheszie var = _var;
ARC
中,默认修饰
- 基本数据类型
@property (atomic, assign)
- 对象数据类型
@property (atomic, strong)
修饰词解释
-
nonatomic
非原子性访问,不对set方法加锁,不是安全线程,但是性能高。 -
atomic
原子性访问,对生成的 set 方法加互斥锁 @synchronized(锁对象),安全线程(不是绝对安全线程),性能差。 -
strong
ARC中使用,修饰OC对象,拥有关系
,引用计数器+1。 -
reatain
MRC中使用,修饰OC对象,拥有关系
,引用计数器+1。 -
assign
修饰基础数据类型,直接赋值,非拥有关系
,不使用引用计数器。 -
weak
修饰协议,控件,非拥有关系
,指向的对象销毁,指针会自动置为nil,不使用引用计数器。 -
unsafe_unretained
与weak类似,不会自动nil化,如果所指向的内存区域被释放了,这个指针就是一个野指针。 -
copy
在 MRC 时是这样做的 release 旧对象( 旧对象的引用计数器 -1 ) , copy 新对象( 新对象的引用计数器 +1 ) , 然后指向新对象 .(新对象是指最终指向的那个对象,不管深拷贝还是浅拷贝),在 ARC 时是这么干的 copy 新对象( 新对象的引用计数器 +1 ) , 然后指向新对象。 -
readonly
只生成get方法,不想把暴露的属性被人随便替换时 , 可以使用。 -
readwrite
生成get/set方法。
@dynamic
告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)
@synthesize
如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。
@synchronized
线程同步锁
问题:
(1)什么情况使用 weak 关键字?相比 assign 有什么不同?
- 使用
- 协议声明使用weak
- IBOutlet 使用weak
- weak 和 assign 的不同点:
weak 策略在属性所指的对象遭到摧毁时,系统会将 weak 修饰的属性对象的指针指向 nil,在 OC 给 nil 发消息是不会有什么问题的;如果使用 assign 策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象已经被销毁,这时候就产生了野指针,如果这时候在给此对象发送消息,很容造成程序奔溃assigin 可以用于修饰非 OC 对象,而 weak 必须用于 OC 对象。
(2)使用 atomic 一定是线程安全的吗?
- 不是,atomic 的本意是指属性的存取方法是线程安全的,并不保证整个对象是线程安全的。
例如: 声明一个 NSMutableArray 的原子属性 stuff,此时 self.stuff 和 self.stuff =othersulf 都是线程安全的。但是,使用[self.stuff objectAtIndex:index]就不是线程安全的,需要用互斥锁来保证线程安全性。
(3)@synthesize 和 @dynamic 分别有什么作用
-
@property 有两个对应的词,一个是@synthesize,一个是@dynamic。
如果@synthesize 和@dynamic 都没写,那么默认的就是
@syntheszie var = _var; -
@synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。
-
@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生成。(当然对于 readonly 的属性只需提供 getter 即可)
-
假如一个属性被声明为@dynamic var;然后你没有提供@setter 方法和@getter 方法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter方法会导致程序崩溃;
或者当运行到 someVar = instance.var 时,由于缺 getter 方法同样会导致崩溃。
(4)ARC 下,不显式指定任何属性关键字时,默认的关键字都有哪些?
-
基本数据:
atomic,readwrite,assign
-
普通的 OC 对象:
atomic,readwrite,strong
(5)用@property 声明的 NSString(或 NSArray,NSDictionary)经常使用 copy 关键字,为什么?如果改用 strong 关键字,可能造成什么问题?
因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
如果我们使用是 strong,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
(6)这个写法会出什么问题: @property(copy)NSMutableArray *array;
因为 copy 策略拷贝出来的是一个不可变对象,然而却把它当成可变对象使用,很容易造成程序奔溃这里还有一个问题,该属性使用了同步锁,会在创建时生成一些额外的代码用于帮助编写多线程程序,这会带来性能问题,通过声明 nonatomic 可以节省这些虽然
很小但是不必要额外开销,在 iOS 开发中应该使用 nonatomic 替代 atomic.
(7)如何让自定义类可以用 copy 修饰符?如何重写带 copy 关键字的 setter?
若想令自己所写的对象具有拷贝功能,则需实现 NSCopying 协议。
// 实现不可变版本拷贝
- (id)copyWithZone:(NSZone *)zone; // 实现可变版本拷贝
- (id)mutableCopyWithZone:(NSZone *)zone;
// 重写带 copy 关键字的 setter
- (void)setName:(NSString *)name {
_name = [name copy];
}
深拷贝和浅拷贝
copy 和 mutableCopy
-
copy
拷贝出来的对象类型总是不可变类型(例如, NSString, NSDictionary, NSArray等等) -
mutableCopy
拷贝出来的对象类型总是可变类型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)
-
copy
对于可变对象为深拷贝,对于不可变对象为浅拷贝 -
mutableCopy
始终是深拷贝
网友评论