#pragma mark - 拷贝的概念
/*
概念:是指对源对象进行拷贝操作,产生一个新的副本对象,这个副本对象与源对象互不影响,相互独立.
*/
// 备注:只有对不可变对象进行copy操作, 才是指针拷贝, 即浅拷贝;
// 备注:使用mutableCopy进行拷贝操作, 都是内容拷贝, 即深拷贝;
#pragma mark - copy
/// copy
- (void)copyMethod
{
#pragma mark - 非集合类
// MARK: 不可变对象
/**
额外知识点:tagged pointer对象
如何识别当前对象为tagged pointer 对象?
答:查看当前对象地址,iOS平台下,二进制最高有效位为1则是,否则不是; MacOS平台下,二进制最低有效位为则是;
*/
/* 字符串长一点, 避免初始化一个tagged pointer 对象, 查看引用计数的时候产生最大值 */
NSString *string = [NSString stringWithFormat:@"123,123,123,123,123,"];
NSString *string_c = string.copy; // 浅拷贝
NSLog(@"s: %p, c: %p", string, string_c);
// FIXME: 结论1.1
/**
浅拷贝产生的副本与源对象地址相同, 此时源对象的引用计数+1. 副本的引用计数与源对象的引用计数相同
*/
// 1. 尝试修改string_c 的值, 查看是否会影响string的值
string_c = @"abcd,abcd,abcd,abcd";
NSLog(@"string: %@, string_c: %@", string, string_c);
// FIXME: 结论1.2
/**
结论:不会影响源对象string, 因为copy操作产生的副本对源对象不产生影响, 同时 string_c的地址会发生改变.
*/
// 2. 尝试使用strong修饰, 查看引用计数及修改值后对源对象的影响
_string_s = string;
string = @"111222333444";
NSLog(@"地址: string: %p, string_s: %p. 值: string: %@, string_s: %@", string, _string_s, string, _string_s);
// FIXME: 结论1.3
/**
结论:修改不可变类型 string的值, 不会影响_string_s的值. 即 修饰不可变类型使用copy与strong效果等同.
*/
// MARK: 可变对象
NSMutableString *string_M = [NSMutableString stringWithString:@"123,123,123,123,123,"];
NSMutableString *string_M_c = string_M.copy;
NSLog(@"s: %p, c: %p, class: %@", string_M, string_M_c, [string_M_c class]);
// FIXME: 结论1.4
/**
结论:不论是可变对象or不可变对象进行copy操作后,都会产生一个不可变类型的对象.
*/
// 尝试:当修改strong修饰的可变类型的对象值时, 会产生怎样的影响?
_string_M_s = string_M;
[_string_M_s appendFormat:@"改了哦"];
NSLog(@"string_M_s: %p, %@; string_M: %p, %@", _string_M_s, _string_M_s, string_M, string_M);
// FIXME: 结论1.5
/**
结论:当修改strong修饰的可变类型的对象值时, 被其引用的对象值也会被修改. 故平时开发时, 可变类型的对象修饰关键字没有特殊需求尽量使用copy修饰, 避免在未知情况下, 导致源数据被修改而未被发现, 导致产生不必要的事故.
*/
#pragma mark - 集合类对象
// MARK: 不可变对象
// NSArray, NSDictionary, NSSet, etc.
/**
与非集合类对象的不同点在于, 集合类对象中的元素不发生变化, 只有集合对象遵守copy规则.
*/
/// e.g.
NSNumber *n1 = @(1);
NSNumber *n2 = @(2);
NSNumber *n3 = @(3);
NSLog(@"before: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
NSArray *array = @[n1, n2, n3];
NSArray *array_c = array.copy;
NSLog(@"s: %p, c: %p", array, array_c);
/**
同结论1.1
结论:copy不可变类型, 产生的副本与源对象地址相同, 即副本的指针指向源对象, 即浅拷贝.
*/
NSLog(@"after: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
// FIXME: 结论1.6
/**
结论:copy不会对集合类的对象内部元素产生影响.
*/
// MARK: 可变对象
NSMutableArray *array_M = [NSMutableArray arrayWithObjects:n1, n2, n3, nil];
NSMutableArray *array_M_c = array_M.copy;
NSLog(@"s: %p, c: %p", array_M, array_M_c);
/**
同结论1.4
结论:copy可变类型, 产生的副本与源对象地址不同, 内容相同, 即深拷贝(内容拷贝).
*/
NSLog(@"after: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
/**
同结论1.6
结论:copy不会对集合类的对象内部元素产生影响.
*/
}
#pragma mark - mutableCopy
- (void)mutableCopyMethod
{
#pragma mark - 非集合类
// MARK: 不可变对象
NSString *string = [NSString stringWithFormat:@"123,123,123,123,123,"];
NSString *string_c = string.mutableCopy; // 深拷贝
NSLog(@"s: %p, c: %p, class: %@", string, string_c, [string_c class]);
// FIXME: 结论2.1
/**
结论:mutalbeCopy产生的副本与源对象地址不同, 内容相同且是可变类型的对象, 即深拷贝.
*/
// MARK: 可变对象
NSMutableString *string_M = [NSMutableString stringWithString:@"123,123,123,123,123,"];
NSMutableString *string_M_c = string_M.mutableCopy;
NSLog(@"s: %p, c: %p, class: %@", string_M, string_M_c, [string_M_c class]);
// FIXME: 结论2.2
/**
结论:不论是可变对象or不可变对象进行mutableCopy操作后,都会开辟一块新的内存, 且产生一个可变类型的对象.
*/
#pragma mark - 集合类对象
// MARK: 不可变对象
// NSArray, NSDictionary, NSSet, etc.
/**
与非集合类对象的不同点在于, 集合类对象中的元素不发生变化, 只有集合对象遵守copy规则.
*/
/// e.g.
NSNumber *n1 = @(1);
NSNumber *n2 = @(2);
NSNumber *n3 = @(3);
NSLog(@"before: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
NSArray *array = @[n1, n2, n3];
NSArray *array_c = array.mutableCopy;
NSLog(@"s: %p, c: %p, class: %@", array, array_c, [array_c class]);
/**
同结论2.1
结论:mutalbeCopy产生的副本与源对象地址不同, 内容相同且是可变类型的对象, 即深拷贝.
*/
NSLog(@"after: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
/**
同结论1.6
结论:mutalbeCopy不会对集合类的对象内部元素产生影响.
*/
// MARK: 可变对象
NSMutableArray *array_M = [NSMutableArray arrayWithObjects:n1, n2, n3, nil];
NSMutableArray *array_M_c = array_M.copy;
NSLog(@"s: %p, c: %p", array_M, array_M_c);
/**
同结论2.1
结论:copy可变类型, 产生的副本与源对象地址不同, 内容相同, 即深拷贝(内容拷贝).
*/
NSLog(@"after: n1 = %p, n2 = %p, n3 = %p", n1, n2, n3);
/**
同结论1.6
结论:copy不会对集合类的对象内部元素产生影响.
*/
}