美文网首页iOS开发技巧iOS DeveloperiOS 开发
NSString属性到底用copy还是strong

NSString属性到底用copy还是strong

作者: 隔壁小鱼 | 来源:发表于2016-08-14 19:57 被阅读236次

    这个问题其实很简单, 但比较容易让人忽略.
    解释这个问题前, 首先要明白, NSString属性为什么要用copy来修饰?
    NSString属性之所有用copy来修饰, 是为了防止不同的指针变量指向同一个内存地址, 从而形成连带效应----就是改变一个变量的值, 另一个值也随之发生改变.比如:

    @interface Demo()@property (strong, nonatomic)  
     NSString *S;
    @end
    
    @implementation 
    
    NSMutableString *MS = [[NSMutableString alloc] initWithString:@"ABC"];
    _S = MS;
    
    @end
    

    这段代码里, 如果NSString属性不用copy而用strong修饰的话, 就会造成两个指针变量同时指向同一块存储空间的问题.具体原因如图:

    这里写图片描述

    代码中的"ABC"是存放在堆中的. 因为NSMutableString的initWithSring方法会将传入的参数从常量区中拷贝一份, 放入堆中.

    这种情况下, 由于NSMutableString的特点就是只会对同一块内存进行操作, 所以不管是改变可变字符串"MS"的值, 还是改变实例对象"S"的值, 另一个对象的值也都会随之发生改变. 这样代码的管理就会非常混乱.

    而如果用copy修饰的话, 在赋值的时候, 编译器会在setter方法中进行判断: 如果等号左边是一个可变字符串, 就让等号左边的指针变量指向一个copy出来的新地址, 这样就可以解决上面的问题.

    如图:


    这里写图片描述

    那么, 为什么开发中NSString属性可以用strong呢?

    因为实际开发中, 几乎用不到NSMutableString啊!!!

    我们都是用一个NSString给另一个NSString赋值啊!!!
    比如:

    @interface Demo()@property (strong, nonatomic) 
    NSString *S;
    @end
    
    @implementation
     NSString *MS = @"ABC";
    _S = MS;
    
    @end
    

    这样的话, 在内存中就变成了:


    这里写图片描述

    这样看似两个指针变量又都指向了同一块内存, 但因为指向的是常量区, 而常量区的内容是不可改变的, 所以即使任何一方改变了指针指向中的内容, 编译器都会重新在常量区中开辟一块空间来保存新的内容, 然后改变该指针的指向, 让它重新指向新的内容.

    比如

    @implementation
     NSString *MS = @"ABC";
    _S = MS;
    MS = @"EFG"
    @end
    

    内存示意图如下:


    这里写图片描述

    正是因为这样, 我们才可以在开发中将NSString属性的策略定义成strong.

    那么用strong修饰NSString的意义何在呢?

    前面提到过, 如果你用copy修饰了NSString, 那么编译器会在setter方法里进行判断参数和对象是可变还是不可变, 判断当然要消耗性能, 想想一个项目里有多少个字符串, 每一个字符串都消耗一点点性能, 那么多字符串加起来消耗的性能也是比较多的, 所以如果用strong来修饰, 可以在一定程度上减少一点无谓性能牺牲.(这也是我在开发中访问属性一直用"_"而不是"self."的原因)

    当然, 如果用strong修饰了NSString属性的话, 必须要确保的就是将来给这个属性赋值时, 用的同样是NSString, 而不是NSMutableString

    相关文章

      网友评论

        本文标题:NSString属性到底用copy还是strong

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