Property

199 阅读4分钟

1.@property

一种更加便捷的构造成员的方式

  • Object-C的属性通过@property自动生成getter和setter方法
  • 在OC当中setter方法和getter方法都可以通过点语法快速访问
  • 自动生成 “ _” + “变量名” 的实例变量
  • 注意重写setter和getter方法,小心递归调用自身
    • 重写setter不要使用self.进行赋值
    • 重写getter不要使用用self.访问属性值

attribute的写法

@interface Person : NSObject
{
    NSString *_name;
    NSUInteger _age;
}

//自己声明
- (void)setName:(NSString*)name;
- (NSString*)name;
- (void)setAge:(NSUInteger)age;
- (NSUInteger)age;
@end

@implementation Person
//自己实现
- (void)setName:(NSString*)name {
    _name = [name copy];
}

- (NSString*)name {
    return _name;
}

- (void)setAge:(NSUInteger)age {
    _age = age;
}

- (NSUInteger)age {
    return _age;
}

@end

property的写法

@interface Person : NSObject

@property (nonatomic, copy) NSString* name;
@property (nonatomic, assign) NSUInteger age;

@end

@implementation Person

//有需要可以重写setter 或者 getter方法
- (void)setName:(NSString*)name {
    _name = [name copy];
}

- (NSString*)name {
    return _name;
}

@end

2.property修饰符

线程安全

  • atomic

    原子性,默认,使用线程保护技术,消耗系统资源,生成自旋锁,多个线程同一时间只能有一个线程对其进行访问。
    • 原子性指的是一个操作不会被CPU中途叫停,然后再调度,不会被中断,要么执行完,要么不执行。
    • 自旋锁在上一个线程没有执行完毕的时候,下一个线程会一直等待,不会睡眠,上一个线程执行完毕,下一个线程立刻执行。而互斥锁在等待的时候会进入睡眠状态,在上一个线程执行完毕之后,会被唤醒,然后再执行
    • atomic需要耗费大量的资源,执行效率低
    • atomic并不保证线程安全,它只会保证set内部安全,在外部不能保证安全
  • nonatomic

    非原子性,没有多线程同时访问的情况下时使用

访问权限

  • readwrite

    默认,同时生成getter与setter的方法,可读可写
  • readonly

    只读,只会生成getteer方法 内存管理
  • assign

    适用一些标量类型(int、long、char、float、double、Integer、CGFloat、Bool)

  • strong

    强引用,只有OC当中的对象才能用到该属性,它使对象的引用计数加1。

  • weak

    弱引用,只是进行引用,没有声明对该对象的拥有权,不会增加引用计数。

  • copy

  • 常见比较

    • strong和retain

      • 相同点:都是对对象进行内存管理,修饰基本数据类型会保存,都会增加对象的引用计数,set时先release掉旧的对象,将新的对象赋值给属性并进行一次retain
      • 不同点:strong用于ARC,retain用于MRC
    • assgin和weak

      • 相同点:都不会增加引用计数
      • 不同点:assign可以修饰基本数据类型,也可以修饰OC对象,指向OC对象后,如果指向的对象被释放,需要手动置为nil;weak只能修饰OC对象,如果指向的对象消失后,自动置为nil,不会产生野指针。
    • strong与copy

      • 浅拷贝:指针拷贝,不会产生新的对象,源对象的引用计数加1,多了一个使用该内存的指针,公用一块内存
      • 深拷贝:对象拷贝,内容拷贝,会产生新的对象,源对象的引用计数不变;两个内存是不同的空间,两个指针指向不同的内存,互不干涉 NSObject提供了copy和mutableCopy两种拷贝方式
      • 如果源对象也是NS* 类型,副本对象采用copy方法进行拷贝是浅拷贝,采用mutableCopy进行拷贝是深拷贝
      • 如果源对象是NSMutable* 类型,副本对象采用copy或者mutableCopy都会进行深拷贝
      对于strong和copy修饰的property
      • 相同点:对于不可变对象都是浅拷贝
      • 不同点: strong修饰的属性对于可变对象依然进行浅拷贝; copy修饰的属性对于可变对象是用深拷贝

3.最佳实践

  • 基本类型用assign
  • delegate用weak
  • NSArray,NSDictionary和NSString,blcok用copy
  • 其他用strong
  • 避免出现环 A->strong -> B - strong -> C - strong -> A
    为什么block要用copy
    • block内部没有调用外部变量时存放在全局区(ARC和MRC下均是),这个时候不会有什么问题
    • block使用了外部局部变量,MRC时block存放到栈上,栈区创建的对象在作用域外会被销毁,销毁后再调用可能会造成程序崩溃,使用copy之后block放在堆区,所以使用copy。在ARC当中的block都会在堆上,系统默认对block进行copy操作,将栈区的对象赋给strong修饰的属性默认也会copy,使用copy表明一致