再回顾:iOS copy与mutableCopy

#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不会对集合类的对象内部元素产生影响.
         */
}

你可能感兴趣的:(再回顾:iOS copy与mutableCopy)