OC NSString在@property中strong和copy的区别

OC NSString在@property中strong和copy的区别

定义一个strong修饰的字符串属性testString1
定义一个copy修饰的字符串属性testString2

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSString *testString1;
@property (nonatomic, copy) NSString *testString2;

@end

**

测试代码

**

// 浅复制1
- (IBAction)shallowCopy1Action:(id)sender {
    NSString *string = [NSString stringWithFormat:@"MyTest"];
    self.testString1 = string;   // 指向同一块内存空间
    self.testString2 = string;   // 浅拷贝,拷贝指向对象的指针,指向同一块内存空间

    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
    string = [NSString stringWithFormat:@"123456"];
    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
}

打印输出

2020-04-01 19:45:15.593923+0800 CopyDemo[3910:52418] string       = MyTest 指针地址 = 0xfb5fa968f64c2397
2020-04-01 19:45:15.594247+0800 CopyDemo[3910:52418] _testString1 = MyTest 指针地址 = 0xfb5fa968f64c2397
2020-04-01 19:45:15.594386+0800 CopyDemo[3910:52418] _testString2 = MyTest 指针地址 = 0xfb5fa968f64c2397
2020-04-01 19:45:15.594507+0800 CopyDemo[3910:52418] string       = 123456 指针地址 = 0xfb5b8d0de0389457
2020-04-01 19:45:15.594666+0800 CopyDemo[3910:52418] _testString1 = MyTest 指针地址 = 0xfb5fa968f64c2397
2020-04-01 19:45:15.594816+0800 CopyDemo[3910:52418] _testString2 = MyTest 指针地址 = 0xfb5fa968f64c2397

分析:
我们可以看到,在string赋值成@“123456”之前,string、self.testString1和self.testString2都指向同一块内存空间,内容自然也相同。

(1) 当来源对象也是NSString的时候,strong和copy一样
(2) copy操作如果来源对象是否可变,如果来源对象是不可变对象(NSString),则只拷贝指针,也就是浅拷贝;
(3) copy操作如果来源对象是可变对象(NSMutableString),则拷贝对象内容,也就是深拷贝

string赋值成@“123456”之后,string指向了新的一块内存空间,也就是@"123456"的内存空间;
而self.testString1和self.testString2仍指向之前的一块内存空间,也就是@"MyTest"的内存空间,所以内容还是@“MyTest”

再来一段代码(有陷阱)

// 深复制1
- (IBAction)deepCopy1Action:(id)sender {
    NSMutableString *string = [NSMutableString stringWithString:@"MyTest"];
    _testString1 = string;   // 复制对象指针地址
    _testString2 = string;   // 复制对象指针地址
    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
    [string appendString:@"...."];
    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
}

**

打印输出

**

2020-04-01 19:55:00.595529+0800 CopyDemo[4311:63637] string       = MyTest 指针地址 = 0x600000beadc0
2020-04-01 19:55:00.595841+0800 CopyDemo[4311:63637] _testString1 = MyTest 指针地址 = 0x600000beadc0
2020-04-01 19:55:00.595991+0800 CopyDemo[4311:63637] _testString2 = MyTest 指针地址 = 0x600000beadc0
2020-04-01 19:55:00.596119+0800 CopyDemo[4311:63637] string       = MyTest.... 指针地址 = 0x600000beadc0
2020-04-01 19:55:00.596228+0800 CopyDemo[4311:63637] _testString1 = MyTest.... 指针地址 = 0x600000beadc0
2020-04-01 19:55:00.596332+0800 CopyDemo[4311:63637] _testString2 = MyTest.... 指针地址 = 0x600000beadc0

这次为什么,内容和指针地址同步了,都一样?
在[string appendString:@"…"];这个语句执行前,string、self.testString1和selfString2都指向同一块内存空间,内容自然也相同;
本质原理:
用@property来声明属性变量时,编译器会自动生成一个以下划线加属性名命名的实例变量
(@synthesize testString1 = _testString1)
(@synthesize testString2 = _testString2)
并且生成对应的getter和setter方法,对于copy修饰的testString2,setter方法中有一条语句:_testString2 = [testString2 copy];
用_testString2 = string; 并没有调用testString2的setter方法
用self.testString2 = string才会调用testString2的setter方法
所以,string、self.testString1和self.testString2和string指向的是同一块内存空间,内容也相同;
[string appendString:@"…"];并没有改变内存空间地址,在字符串尾部添加了@"…"

// 深复制1
- (IBAction)deepCopy1Action:(id)sender {
    NSMutableString *string = [NSMutableString stringWithString:@"MyTest"];

    self.testString1 = string;    // 指向同一块内存空间
    self.testString2 = string;    // 深拷贝,拷贝对象内容,放入重新开辟的一片内存空间
    // 当指向对象也是NSMutableString的时候,strong和copy不一样
    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
    [string appendString:@"...."];
    NSLog(@"string       = %@ 指针地址 = %p", string, string);
    NSLog(@"_testString1 = %@ 指针地址 = %p", self.testString1, self.testString1);
    NSLog(@"_testString2 = %@ 指针地址 = %p", self.testString2, self.testString2);
}
打印输出:
2020-04-01 20:09:29.139054+0800 CopyDemo[4561:70490] string       = MyTest 指针地址 = 0x60000164d770
2020-04-01 20:09:29.139231+0800 CopyDemo[4561:70490] _testString1 = MyTest 指针地址 = 0x60000164d770
2020-04-01 20:09:29.139361+0800 CopyDemo[4561:70490] _testString2 = MyTest 指针地址 = 0xbe43ad479fcbd6af
2020-04-01 20:09:29.139474+0800 CopyDemo[4561:70490] string       = MyTest.... 指针地址 = 0x60000164d770
2020-04-01 20:09:29.139591+0800 CopyDemo[4561:70490] _testString1 = MyTest.... 指针地址 = 0x60000164d770
2020-04-01 20:09:29.139704+0800 CopyDemo[4561:70490] _testString2 = MyTest 指针地址 = 0xbe43ad479fcbd6af

string和self.testString1指向同一块内存空间,地址相同,内容相同;
self.testString2重新复制string的内容,重新开辟了一块内存空间,当string的内容发生改变,并不会影响self.testString2的内容;

总结:

(1) 当来源对象也是NSString的时候,strong和copy一样
(2) copy操作如果来源对象是否可变,如果来源对象是不可变对象(NSString),则只拷贝指针,也就是浅拷贝;
(3) copy操作如果来源对象是可变对象(NSMutableString),则拷贝对象内容,也就是深拷贝

**

浅拷贝,也就是浅复制,本质是拷贝对象指针;
深拷贝,也就是深复制,本质是拷贝对象内容;

**

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值