关于 NSString 使用 copy 和 strong 修饰的

作者: afishhhhh | 来源:发表于2016-10-01 21:48 被阅读419次

    第一种情况: 使用 copy 修饰

    // 代码片段1
    // Person.h
    @interface Person : NSObject
    @property (nonatomic, copy) NSString *lastName;
    @end
    
    // Person.m
    @implementation Person
    - (instancetype)init {
        self = [super init];
        if (self) {
            _lastName = @"name";
        }
        return self;
    }
    @end
    
    // main.m
    int main(int argc, const char * argv[]) {
        Person *p1 = [[Person alloc] init];
        NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
        
        NSMutableString *newLastName = [[NSMutableString alloc] initWithString:@"newname"];
        NSLog(@"newLastName = %@, newLastName address = %p", newLastName, newLastName);
        
        p1.lastName = newLastName;
        NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
        
        return 0;
    }
    

    以上代码执行后的结果如下:

    lastname = name, lastname address = 0x100001078
    newLastName = newname, newLastName address = 0x1003031e0
    lastname = newname, lastname address = 0x100303720
    

    从以上打印的结果可以看到,第一次打印的 lastname address和第二次打印的 lastname address 结果并不相同,同时 newLastName address 和第二次打印的 lastname address 也不相同,说明执行 p1.lastName = newLastName 之后 p1.lastName 指向了一块全新的内存空间。

    在这里,由于 copy 的作用,在赋值的过程中,newLastName 产生了一个不可变的副本,而 p1.lastName 则指向此副本。所以对 newLastName 做一些操作的时候是不会影响到 p1.lastName 的。

    改变一: 修改 main 方法中的代码

    NSString *newLastName = @"newname";
    

    在执行 p1.lastName = newLastName 语句之后,两者指向同一个地址,仅仅是简单的赋值操作。

    第二种情况: 使用 strong 修饰

    将代码:

    @property (nonatomic, copy) NSString *lastName;
    

    修改为:

    @property (nonatomic, strong) NSString *lastName;
    

    执行代码片段1之后的结果如下:

    lastname = name, lastname address = 0x100001068
    newLastName = newname, newLastName address = 0x100202e00
    lastname = newname, lastname address = 0x100202e00
    

    从以上结果中发现第一次打印的 lastname address 和第二次打印的 lastname address 指向不同的内存,但是第二次打印的 lastname addressnewLastName address 相同,说明,与 copy 不同的是,strong 并没有开辟一块新的内存空间,而是直接将 lastname 指向了 newLastName

    改变一: 修改 main 方法中的代码,在 return 0 之前添加以下代码

    [newLastName appendString:@"abc"];
    NSLog(@"newLastName = %@, newLastName address = %p", newLastName, newLastName);
    NSLog(@"lastname = %@, lastname address = %p", p1.lastName, p1.lastName);
    

    打印结果如下:

    newLastName = newnameabc, newLastName address = 0x100202e00
    lastname = newnameabc, lastname address = 0x100202e00
    

    因为 newLastNamep1.lastname 指向同一个内存,对 newLastName 的改变也就改变了 p1.lastname。但是 lastname 属性是不可变的 NSString 类型,而在这里却发生了改变。

    结论

    copy 修饰的 NSString 如果在无意中被一个 NSMutableString 类型的变量赋值,该 NSMutableString 类型的变量会被 copy 出一个不可变副本,将该副本赋值给 NSString 类型的变量,万一 NSMutableString 的值被修改,不会影响到 NSString 的值。

    strong 修饰的 NSString 如果在无意中被一个 NSMutableString 类型的变量赋值,则直接将指针指向该 NSMutableString 类型的变量,一旦 NSMutableString 的值被修改,NSString 的值也就发生了改变,这与 NSString 作为不可变类型相违背。

    当然如果 NSString 被一个 NSString 赋值,copy 的效果与 strong 的效果是一样的,直接改了就是。

    相关文章

      网友评论

        本文标题:关于 NSString 使用 copy 和 strong 修饰的

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