美文网首页
属性修饰符用法

属性修饰符用法

作者: 天顾有情人_strive | 来源:发表于2017-01-06 09:26 被阅读28次

    assign 修饰符用来修饰值类型和 id 类型(一般是 delegate)的属性,需要注意的是如果 id 类型的属性的修饰符用了 assign, 当你不再需要这个属性时,你必须将 delegate 手动置空,防止野指针产生,这也是为什么 delegate 一般都用 weak 修饰的原因。

    weak 和 strong 是 ARC 的产物,分别表示弱引用类型和强引用类型。在给 strong 修饰的属性赋值时,会将属性的指针指向新值的地址,同时持有这个新值(新值的引用计数被加1)。在给 weak 修饰的属性赋值时,只是简单地将属性的指针指向新值的地址,不会持有新值。

    retain 在 ARC 下基本等同于 strong。

    copy 表示强引用,但是不会持有新值,而是拷贝一份引用计数为1的值给属性。给这种修饰符修饰的属性赋值时,实际上是把 新值调用 copy 方法后的返回值 赋给属性。NSString 类型常常用 copy 修饰,就是防止修改某个对象后,对强引用这个对象的属性造成不必要影响。

    引用类型默认的修饰符是 strong.

    值类型的默认修饰符是 assign.

    Copy 传入的不是值,是对象。

    Copy只能用于那些实现了NSCopying这个协议的类,否则会崩溃。按照字面意思,Copy即拷贝一份。一般来说,用户自己定义并实现了NSCopying的类,Copy的作用是在内存上再开辟空间,然后将调用者拷贝进去,所以对调用对象来说,它的引用计数并没有变化。

    另外值得注意的是,像一些不可变类型,如NSString,NSArray,NSDictionary,NSSet之类,Copy并不会在内存上开辟新空间,而是为调用者的引用计数+1,等同于Retain。

    这里不得不提声明Property里的修饰词作用了,声明一个Property目的是为了让编译器为我们自动合成Setter和Getter方法,如果我们不想编译器帮我们合成的话,我们可以这么写(基于ARC):

    {

    NSString *_value;

    }

    - (void)setValue:(NSString *)value {

    _value = value;

    }

    - (NSString *)value {

    return _value;

    }

    上面这种写法是存在一定问题的,往后再讲解。

    编译器为我们合成的实现大概是这样子:

    @property (nonatomic, copy) NSString *value;

    - (void)setValue:(NSString *)value {

    _value = value.copy;

    }

    - (NSString *)value {

    return _value;

    }

    注意这里的copy,如果不用Copy修饰的话,跟第一个实现类似。

    考虑一下这段代码会发生什么事,如果没有修饰为Copy时:

    NSMutableString *mString = [[NSMutableString alloc] initWithString:@"string"];

    self.value = mString;

    这里创建一个可变的字符串对象,并赋值给了一个声明为不可变的字符串对象。这样导致本来指向不可变字符串对象的value指向了一个可变字符串对象。

    但如果用了Copy修饰,那么在赋值前,可变的字符串对象先Copy为不可变字符串对象,再赋值到value上,这样就可以避免一些不可避免错误发生。

    所以对这些不可变类的声明需要用Copy而不是Strong

    意思就是说 NSString,NSArray,NSDictionary,NSSet等 这些不可变的类都要用copy。

    相关文章

      网友评论

          本文标题:属性修饰符用法

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