美文网首页iOS
OC属性&修饰符理解

OC属性&修饰符理解

作者: One1丨光 | 来源:发表于2017-10-21 16:17 被阅读30次

    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. 属性修饰符

    1. nonatomic/atomic

      1. nonatomic
        • 线程不安全 多个线程可以同时对其进行访问,没有资源保护
        • 访问速度快
      2. atomic
        • 线程安全 在多线程中只能有一个线程对进行访问,会默认会setter方法加锁(MRC环境重写Setter方法需要设置访问锁)
        • 访问效率慢
    2. assign/weak

      1. assign
        • 修饰基本数据类型(非指针型变量)setter方法里不会进行任何retain操作
        • assign如果拿来修饰对象类型会有野指针(悬垂指针)的危险。(MRC使用unsafe_unretained修饰对象类型).assign修饰对象的话,如果对象释放了不会置为nil|
      2. weak
        • 修饰对象类型。Arc下使用 和assign的效果一致
        • weak比assign优化的一点是,当对象释放了以后可以将修饰的指针置为nil,可以有效避免野指针的行为
    3. 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,则对象被赋值了一个可变对象的时候,不可变对象的内容就可以发生改变了.容易造成语义的矛盾,也极有影响代码的运行。

    1. readonly/readwrite

      readwrite就是可读写,不加这个属性修饰符默认就是如此,所有变量都是可以读写的,也就是都自带setter和getter方法,而使用readonly修饰系统会自动生成getter方法而不生成setter方法所以是只读的,无法赋值。

    3.另外一些标示符

    1. const

      NSString const *str = @"123";
      NSString * const str1 = @"123";
      str = @"456"; // 这句话只是把456的内存地址分配给str 
      str 本身是一个变量,但它指向的内存是不可变的
      str1 本身是一个常量,*str1 是一个变量
      

      const 相比 宏定义define:

       1. const 在编译阶段参与编译,宏则是在预编译阶段
       2. 宏不做类型检查,只是替换内容,const 会编译检查类型
       3. 宏可以定义函数方法代码块,const不行
      
    2. static
      static 修饰的变量都是在字符常量区

      1. static 修饰全部变量
        • 限制了全局变量的作用域为当前文件内
      2. static 修饰局部变量
        • 让局部变量只初始化一次
        • 局部变量在程序中只有一份内存
        • 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期
    3. extern

      对extern来说,可以理解为扩展吧,将当前变量的作用域从一个类扩展到另一个类。

    相关文章

      网友评论

        本文标题:OC属性&修饰符理解

        本文链接:https://www.haomeiwen.com/subject/puwiuxtx.html