属性关键词

镇楼专用

@property

默认格式:@syntheszie var = _var;

ARC中,默认修饰

  • 基本数据类型@property (atomic, assign)
  • 对象数据类型@property (atomic, strong)

修饰词解释

  • nonatomic 非原子性访问,不对set方法加锁,不是安全线程,但是性能高。

  • atomic 原子性访问,对生成的 set 方法加互斥锁 @synchronized(锁对象),安全线程(不是绝对安全线程),性能差。

  • strongARC中使用,修饰OC对象,拥有关系,引用计数器+1。

  • reatainMRC中使用,修饰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 有什么不同?

  • 使用
  1. 协议声明使用weak
  2. 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 始终是深拷贝

你可能感兴趣的:(属性关键词)