iOS 属性修饰符

「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战」。

@property 有两个的作用:一是自动生成私有属性(一般是下划线+属性名),而是自动生成 gettersetter 方法。
声明属性时,紧跟在 @property 之后的属性修饰符则描述了自动生成 gettersetter 方法的规则。

根据MRC和ARC划分属性修饰符的使用范围:
MRC:nonatomic,atomic,retain,assign,copy,readwrite,readonly
ARC:nonatomic,atomic,strong,weak,assign,copy,readwrite,readonly

  • nonatomic

    • nonatomic 表示非原子属性

      • 并发访问性能高,但是访问不安全

        • 它直接访问内存中的地址,不关心其他线程是否在改变这个值,并且中间没有死锁保护;所以可能拿不到完整的值
  • atomic

    • atomic 表示原子属性

      • 系统生成的 getter/setter 会保证 get、set 操作的完整性,不受其他线程影响

        • 系统生成的 getter/setter 方法中,使用了 @synchronized(self)
        • 如果一个线程正在执行 getter/setter,其他线程就得等待
      • 如果有另一个线程同时在调 [property release],那可能就会crash,因为 release 不受 getter/setter 操作的限制。

        • 也就是说,atomic 修饰的属性只能说是读/写安全的,但并不是线程安全的

          • 因为别的线程还能进行读写之外的其他操作。
          • 线程安全需要开发者自己来保证。
    • 系统默认的属性是 atomic

  • strong

    • strong 表示对对象的强引用

      • 强引用时,引用计数会 +1
      • 给 strong 属性赋值时,setter 方法中会先 release 旧值再 retain 新值并赋值
      • 两个对象之间相互强引用会造成循环引用,内存泄漏
  • weak

    • weak 表示对象的弱引用

      • 弱引用时,不会使传入的对象计数+1

      • 被其修饰的对象随时可能被系统销毁回收

        • 当该对象的引用计数为 0,则会被回收,对象被释放以后,weak 指针会被自动设置为 nil

          在OC的运行时环境中,维护了一种 weak 表(哈希表)
          这张哈希表用对象的首地址作为 key,用 weak 指针自身的地址组成的数组作为 value
          当对象被释放后,通过这个对象的起始地址来找到所有指向它的 weak 指针,并将它们指向nil

      • weak 多用于避免循环引用

  • assign

    • assign 主要用于修饰基本数据类型

      • 包括OC基本数据类型(NSInteger,CGFloat)和C数据类型(int, float, double, char)
    • 基本数据类型存储在栈中,内存不用程序员管理。

    • assign 也可以修饰对象,但是当对象被释放后,指针依然指向之前的内存地址。\

      • 此时,访问被释放的地址就会 crash

      • 这个已经被释放了的对象被称为 僵尸对象

    • assign 在 MRC 和 ARC 下都可以使用

猜你喜欢

转载自juejin.im/post/7033341964376342536