简介
NSString字符串
__NSCFConstantString
是常量字符串,存储在数据区。
__NSCFString
表示为oc对象,NSString就是封装的CFString,这个字符串对象存储在堆中。
- NSTaggedPointerString 这个类表示这是字符串的一种指针Tagged Pointer
- 不可变的字符串NSString,用NSString赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @interface ViewController () @property (nonatomic,copy)NSString * strCopy; @property (nonatomic,strong)NSString * strStrong; @end
@implementation ViewController
- (void)viewDidLoad { [super viewDidLoad]; [self demo]; }
- (void)demo{ NSString * str = @"123"; self.strCopy = str; self.strStrong = str; // 改变之前 NSLog(@"str:%@-%p", str, str); NSLog(@"strCopy:%@-%p-%@", self.strCopy, self.strCopy,[self.strCopy class]); NSLog(@"strStrong:%@-%p-%@", self.strStrong, self.strStrong,[self.strStrong class]); // 改变之后 str = @"234"; NSLog(@"str:%@-%p", str, str); NSLog(@"strCopy:%@-%p-%@", self.strCopy, self.strCopy,[self.strCopy class]); NSLog(@"strStrong:%@-%p-%@", self.strStrong, self.strStrong,[self.strStrong class]); }
|
查看打印结果
1 2 3 4 5 6 7
| 2020-08-25 20:40:52.062970+0800 OC-copy和strong[44465:2260522] str:123-0x101b1c028 2020-08-25 20:40:52.063214+0800 OC-copy和strong[44465:2260522] strCopy:123-0x101b1c028-__NSCFConstantString 2020-08-25 20:40:52.063389+0800 OC-copy和strong[44465:2260522] strStrong:123-0x101b1c028-__NSCFConstantString
2020-08-25 20:40:52.063510+0800 OC-copy和strong[44465:2260522] str:234-0x101b1c0a8 2020-08-25 20:40:52.063629+0800 OC-copy和strong[44465:2260522] strCopy:123-0x101b1c028-__NSCFConstantString 2020-08-25 20:40:52.063743+0800 OC-copy和strong[44465:2260522] strStrong:123-0x101b1c028-__NSCFConstantString
|
我们发现:
结论:
使用 NSString 赋值给 NSString 的时候,无论使用 copy 还是 strong 都是 深拷贝
- 不可变的字符串NSString,用NSMutableString赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| - (void)demo1{ NSMutableString * mstr = [NSMutableString stringWithFormat:@"123"]; self.strCopy = mstr; self.strStrong = mstr; // 改变之前 NSLog(@"str:%@-%p", str, str); NSLog(@"strCopy:%@-%p-%@", self.strCopy, self.strCopy,[self.strCopy class]); NSLog(@"strStrong:%@-%p-%@", self.strStrong, self.strStrong,[self.strStrong class]); // 改变之后 str = @"234"; NSLog(@"str:%@-%p", str, str); NSLog(@"strCopy:%@-%p-%@", self.strCopy, self.strCopy,[self.strCopy class]); NSLog(@"strStrong:%@-%p-%@", self.strStrong, self.strStrong,[self.strStrong class]); }
|
打印结果
1 2 3 4 5 6 7 8
| 2020-08-25 20:51:56.553156+0800 OC-copy和strong[44569:2268592] str:123-0x60000192f9c0-__NSCFString 2020-08-25 20:51:56.553390+0800 OC-copy和strong[44569:2268592] strCopy:123-0xb174ce39c84cf2fe-NSTaggedPointerString 2020-08-25 20:51:56.553533+0800 OC-copy和strong[44569:2268592] strStrong:123-0x60000192f9c0-__NSCFString
2020-08-25 20:51:56.553636+0800 OC-copy和strong[44569:2268592] str:123456-0x60000192f9c0-__NSCFString 2020-08-25 20:51:56.555326+0800 OC-copy和strong[44569:2268592] strCopy:123-0xb174ce39c84cf2fe-NSTaggedPointerString 2020-08-25 20:51:56.555514+0800 OC-copy和strong[44569:2268592] strStrong:123456-0x60000192f9c0-__NSCFString
|
我们发现:
- 用
MutableString
赋值给 NSString
时,copy
拷贝了新的对象,指向新的内存空间,深拷贝
,返回NSTaggedPointerString;
- strong指向同一个内存空间,
浅拷贝
,返回 __NSCFString
结论:使用MutableString赋值时,copy是深拷贝,strong是浅拷贝
NSMutableString字符串
- 不能使用NSString直接赋值给NSMutableString,会报警告
1
| Incompatible pointer types assigning to 'NSMutableString *' from 'NSString *'
|
- 使用NSMutableString赋值给NSMutableString
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| - (void)demo2{ NSMutableString * mstr = [NSMutableString stringWithFormat:@"123"]; self.strMCopy = mstr; self.strMStrong = mstr; // 改变之前 NSLog(@"mstr:%@-%p-%@", mstr, mstr,[mstr class]); NSLog(@"strMCopy:%@-%p-%@", self.strMCopy, self.strMCopy,[self.strMCopy class]); NSLog(@"strMStrong:%@-%p-%@", self.strMStrong, self.strMStrong,[self.strMStrong class]); // 改变之后 [mstr appendFormat:@"456"]; // [self.strMCopy appendFormat:@"7"]; //报错,因为 // [self.strMStrong appendFormat:@"8"]; // 可以正常使用 NSLog(@"mstr:%@-%p-%@", mstr, mstr,[mstr class]); NSLog(@"strMCopy:%@-%p-%@", self.strMCopy, self.strMCopy,[self.strMCopy class]); NSLog(@"strMStrong:%@-%p-%@", self.strMStrong, self.strMStrong,[self.strMStrong class]); }
|
查看结果
1 2 3 4 5 6 7 8
| 2020-08-25 20:59:31.642078+0800 OC-copy和strong[44603:2273858] mstr:123-0x600001c8bb10-__NSCFString 2020-08-25 20:59:31.642335+0800 OC-copy和strong[44603:2273858] strMCopy:123-0xd5ae0af186ac50bb-NSTaggedPointerString 2020-08-25 20:59:31.642466+0800 OC-copy和strong[44603:2273858] strMStrong:123-0x600001c8bb10-__NSCFString
2020-08-25 20:59:31.642608+0800 OC-copy和strong[44603:2273858] mstr:123456-0x600001c8bb10-__NSCFString 2020-08-25 20:59:31.642731+0800 OC-copy和strong[44603:2273858] strMCopy:123-0xd5ae0af186ac50bb-NSTaggedPointerString 2020-08-25 20:59:31.642963+0800 OC-copy和strong[44603:2273858] strMStrong:123456-0x600001c8bb10-__NSCFString
|
由结果可知:
copy拷贝了一个新的对象,指向新的内存地址,深拷贝,返回NSTaggedPointerString;
strong指向同一个内存地址,引用计数+1,返回__NSCFString
数组
- 用NSArray赋值NSArray
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #import "ViewController.h"
@interface ViewController () @property (nonatomic,copy)NSArray * arrCopy; @property (nonatomic,strong)NSArray * arrStrong; @end - (void)demo3{ NSArray * arr = @[@"1",@"2",@"3"]; self.arrCopy = arr; self.arrStrong = arr; NSLog(@"arr:%@-%p", arr, arr); NSLog(@"arrCopy:%@-%p-%@", self.arrCopy, self.arrCopy,[self.arrCopy class]); NSLog(@"arrStrong:%@-%p-%@", self.arrStrong, self.arrStrong,[self.arrStrong class]); arr = @[@"2",@"3",@"4"]; self.arrCopy = arr; self.arrStrong = arr; NSLog(@"arr:%@-%p", arr, arr); NSLog(@"arrCopy:%@-%p-%@", self.arrCopy, self.arrCopy,[self.arrCopy class]); NSLog(@"arrStrong:%@-%p-%@", self.arrStrong, self.arrStrong,[self.arrStrong class]); }
|
打印结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| 2020-08-25 19:25:42.826769+0800 OC-copy和strong[44074:2223987] arr:( 1, 2, 3 )-0x6000037518f0 2020-08-25 19:25:42.827010+0800 OC-copy和strong[44074:2223987] arrCopy:( 1, 2, 3 )-0x6000037518f0-__NSArrayI 2020-08-25 19:25:42.827146+0800 OC-copy和strong[44074:2223987] arrStrong:( 1, 2, 3 )-0x6000037518f0-__NSArrayI 2020-08-25 19:25:42.827452+0800 OC-copy和strong[44074:2223987] arr:( 2, 3, 4 )-0x6000037546c0 2020-08-25 19:25:42.827617+0800 OC-copy和strong[44074:2223987] arrCopy:( 2, 3, 4 )-0x6000037546c0-__NSArrayI 2020-08-25 19:25:42.827748+0800 OC-copy和strong[44074:2223987] arrStrong:( 2, 3, 4 )-0x6000037546c0-__NSArrayI
|
结论:
对于不可变的NSSArray用copy和strong修饰都会指向同一个内存地址,说明是浅拷贝,返回不可变数组。当addObject时,销毁之前的内存地址,重新开辟了一个内存地址
- 用NSMutableArray赋值NSArray
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| - (void)demo4{ NSMutableArray * marr = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]]; self.arrCopy = marr; self.arrStrong = marr; NSLog(@"arr:%@-%p", marr, marr); NSLog(@"arrCopy:%@-%p-%@", self.arrCopy, self.arrCopy,[self.arrCopy class]); NSLog(@"arrStrong:%@-%p-%@", self.arrStrong, self.arrStrong,[self.arrStrong class]); [marr addObject:@"4"]; self.arrCopy = marr; self.arrStrong = marr; NSLog(@"arr:%@-%p", marr, marr); NSLog(@"arrCopy:%@-%p-%@", self.arrCopy, self.arrCopy,[self.arrCopy class]); NSLog(@"arrStrong:%@-%p-%@", self.arrStrong, self.arrStrong,[self.arrStrong class]); }
|
查看结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 2020-08-25 19:34:32.073188+0800 OC-copy和strong[44141:2230084] arr:( 1, 2, 3 )-0x6000026ea850 2020-08-25 19:34:32.073428+0800 OC-copy和strong[44141:2230084] arrCopy:( 1, 2, 3 )-0x6000026eaac0-__NSArrayI 2020-08-25 19:34:32.073589+0800 OC-copy和strong[44141:2230084] arrStrong:( 1, 2, 3 )-0x6000026ea850-__NSArrayM 2020-08-25 19:34:32.073735+0800 OC-copy和strong[44141:2230084] arr:( 1, 2, 3, 4 )-0x6000026ea850 2020-08-25 19:34:32.073950+0800 OC-copy和strong[44141:2230084] arrCopy:( 1, 2, 3, 4 )-0x6000026daca0-__NSArrayI 2020-08-25 19:34:32.074085+0800 OC-copy和strong[44141:2230084] arrStrong:( 1, 2, 3, 4 )-0x6000026ea850-__NSArrayM
|
结论:
copy拷贝了一份新的数组,指向新的内存空间,深拷贝,返回不可变的数组,因此不能作为可变的去添加/删除元素。
strong指向同一个内存地址,引用计数+1,返回的是可变的数组。
不能用NSArray赋值NSMutableArray
用NSMutableArray赋值NSMutableArray
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| - (void)demo5{ NSMutableArray * marr = [NSMutableArray arrayWithArray:@[@"1",@"2",@"3"]]; self.arrmCopy = marr; self.arrmStrong = marr; NSLog(@"marr:%@-%p", marr, marr); NSLog(@"arrmCopy:%@-%p-%@", self.arrmCopy, self.arrmCopy,[self.arrmCopy class]); NSLog(@"arrmStrong:%@-%p-%@", self.arrmStrong, self.arrmStrong,[self.arrmStrong class]); [marr addObject:@"4"]; self.arrmCopy = marr; self.arrmStrong = marr; NSLog(@"marr:%@-%p", marr, marr); NSLog(@"arrmCopy:%@-%p-%@", self.arrmCopy, self.arrmCopy,[self.arrmCopy class]); NSLog(@"arrmStrong:%@-%p-%@", self.arrmStrong, self.arrmStrong,[self.arrmStrong class]); }
|
查看打印结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 2020-08-25 19:45:18.878300+0800 OC-copy和strong[44201:2236266] marr:( 1, 2, 3 )-0x600003f19020 2020-08-25 19:45:18.878571+0800 OC-copy和strong[44201:2236266] arrmCopy:( 1, 2, 3 )-0x600003f191d0-__NSArrayI 2020-08-25 19:45:18.878729+0800 OC-copy和strong[44201:2236266] arrmStrong:( 1, 2, 3 )-0x600003f19020-__NSArrayM 2020-08-25 19:45:18.878872+0800 OC-copy和strong[44201:2236266] marr:( 1, 2, 3, 4 )-0x600003f19020 2020-08-25 19:45:18.879020+0800 OC-copy和strong[44201:2236266] arrmCopy:( 1, 2, 3, 4 )-0x600003f1d410-__NSArrayI 2020-08-25 19:45:18.879145+0800 OC-copy和strong[44201:2236266] arrmStrong:( 1, 2, 3, 4 )-0x600003f19020-__NSArrayM
|
结论:
copy相当于深拷贝,返回不可变的数组
strong相当于浅拷贝,返回可变的数组
字典和数组相同
总结:
- 当原数据是不可变数据时,不管使用strong还是copy修饰,都是指向原来的对象,copy操作只是做了一次浅拷贝。
- 当源数据是可变数据时,strong只是将源数据的引用计数加1,而copy则是对原字符串做了次深拷贝,从而生成了一个新的对象,并且copy的对象指向这个新对象。