oc中copy、strong、weak、assign解析

NSMutableString

  1. “_”方式调用赋值
 NSMutableString *mOriginMutableString = [[NSMutableString alloc] initWithString: @"原始数据"];
    _mCopyMutableString = mOriginMutableString;
    _mStrongMutableString = mOriginMutableString;
    _mWeakMutableString = mOriginMutableString;
    _mAssignMutableString = mOriginMutableString;

 NSLog(@"mOriginMutableString : %p, %@", mOriginMutableString,mOriginMutableString);
    NSLog(@"_mCopyMutableString  : %p, %@", _mCopyMutableString,_mCopyMutableString);
    NSLog(@"_mStrongMutableString: %p, %@", _mStrongMutableString,_mStrongMutableString);
    NSLog(@"_mWeakMutableString  : %p, %@", _mWeakMutableString,_mWeakMutableString);
    NSLog(@"_mAssignMutableString: %p, %@", _mAssignMutableString,_mAssignMutableString);
    NSLog(@"引用计数:%@", [mOriginMutableString valueForKey: @"retainCount"]);

运行结果图如下:
在这里插入图片描述
有结果图,我们发现,赋值后,引用计数为3,指针相同。

  1. 通过“self.”的方式调用赋值
 	self.mCopyMutableString = mOriginMutableString;
    self.mStrongMutableString = mOriginMutableString;
    self.mWeakMutableString = mOriginMutableString;
    self.mAssignMutableString = mOriginMutableString;

结果如图如下:
在这里插入图片描述
我们发现引用计数为2了,这是为什么呢?

因为“self.” 会调用getter、setter方法,“_”方式不会调用getter、setter方法,直接访问实例变量并赋值。

strong 指向原来的内存,并且指针数+1,
week 指向原来的内存,并且指针数不变,
assign指向原来的内存,但是指针数不变。

copy来说,如果是self. 调用是深拷贝,重新开辟内存块,修改原来的值,不会导致现有值改变。

如果是_直接访问,则相当于浅拷贝,指向原来的内存,指数+1。修改原来的值,会影响到现有的值。

week 与 assign来说

week内存释放后,指针变为nil

assign内存释放后,指针不为nil,后期数据改变后,出现野指针,导致程序崩溃

retain 与 strong为同样的功能,retain为ARC出现之前的关键字。

增加指针为强引用,不增加指针是弱引用
重新开辟内存块是深拷贝,使用同一个内存块为浅拷贝

NSMutableArray

  1. 通过“self.”赋值。
   NSMutableArray *mOriginMutableArray = [[NSMutableArray alloc] init];
    NSMutableString *m1 =  [[NSMutableString alloc] initWithString: @"原始数据 1"];
    NSMutableString *m2 =  [[NSMutableString alloc] initWithString: @"原始数据 2"];
    NSMutableString *m3 =  [[NSMutableString alloc] initWithString: @"原始数据 3"];
    
    [mOriginMutableArray addObject:m1];
    [mOriginMutableArray addObject:m2];
    [mOriginMutableArray addObject:m3];
    
    self.mCopyMutableArray = mOriginMutableArray;
    self.mStrongMutableArray = mOriginMutableArray;
    self.mWeakMutableArray = mOriginMutableArray;
    
    NSLog(@"mOriginMutableArray : %p, %@", mOriginMutableArray,mOriginMutableArray);
    NSLog(@"mCopyMutableArray  : %p, %@", _mCopyMutableArray,_mCopyMutableArray);
    NSLog(@"mStrongMutableArray: %p, %@", _mStrongMutableArray,_mStrongMutableArray);
    NSLog(@"mWeakMutableArray  : %p, %@", _mWeakMutableArray,_mWeakMutableArray);
    NSLog(@"引用计数:%@", [mOriginMutableArray valueForKey: @"retainCount"]);
    NSLog(@"%p %p %p %p", &mOriginMutableArray,mOriginMutableArray,mOriginMutableArray[0],mOriginMutableArray[1]);

结果图如下:
在这里插入图片描述

  1. 采用“_”方式调用赋值
    _mCopyMutableArray = mOriginMutableArray;
    _mStrongMutableArray = mOriginMutableArray;
    _mWeakMutableArray = mOriginMutableArray;

结果图如下:
在这里插入图片描述

我们发现引用计数减少的原因和上边的一样,即self. 和_ 调用对copy的影响。

NSMutableArray类的addObject方法,对同一个对象执行N次,这这个对象的指针数就会加上N次,所以我们发现,使用_直接调用时,指针数为2,而不是一。

copy同上边的一样,会重新开辟内存区域,strong、weak和原数据指向同一块内存区域,

所以,copy是深拷贝,strong、weak、assign为浅拷贝。

同时,我们修改数组中的元素时,发现,所有的数据元素都变了, 也就是说,数组中的NSMutableString在拷贝时是浅拷贝。

NSString

  1. “self.”调用
 NSString *mOriginString = @"原始数据";
        self.mCopyString = mOriginString;
        self.mStrongString = mOriginString;
        self.mWeakString = mOriginString;
        self.mAssignString = mOriginString;
    
    NSLog(@"mOriginMutableString : %p, %@", mOriginString,mOriginString);
    NSLog(@"_mCopyMutableString  : %p, %@", _mCopyString,_mCopyString);
    NSLog(@"_mStrongMutableString: %p, %@", _mStrongString,_mStrongString);
    NSLog(@"_mWeakMutableString  : %p, %@", _mWeakString,_mWeakString);
    NSLog(@"_mAssignMutableString: %p, %@", _mAssignString,_mAssignString);
    NSLog(@"引用计数:%@", [mOriginString valueForKey: @"retainCount"]);
    
    NSLog(@"-------------改变值后------------");
    mOriginString = @"新值";
    
    NSLog(@"mOriginMutableString : %p, %@", mOriginString,mOriginString);
    NSLog(@"_mCopyMutableString  : %p, %@", _mCopyString,_mCopyString);
    NSLog(@"_mStrongMutableString: %p, %@", _mStrongString,_mStrongString);
    NSLog(@"_mWeakMutableString  : %p, %@", _mWeakString,_mWeakString);
    NSLog(@"_mAssignMutableString: %p, %@", _mAssignString,_mAssignString);
    NSLog(@"引用计数:%@", [mOriginString valueForKey: @"retainCount"]);

结果图如下:
在这里插入图片描述
2. “_”调用

        _mCopyString = mOriginString;
        _mStrongString = mOriginString;
        _mWeakString = mOriginString;
        _mAssignString = mOriginString;

结果图如下:
在这里插入图片描述
这个比较好理解,直接说结论了:

NSString 和 NSMutableString 基本相同,除了copy,对NSString来说是浅拷贝,对NSMutableString来说是深拷贝。

同时,我们发现通过self. 和 _ 调用,对copy来说都是一样的,都是浅拷贝。

NSArray

 NSString *m1 =  @"Origin 1";
    NSString *m2 =  @"Origin 2";
    NSString *m3 =  @"Origin 3";
    NSArray *mOriginArray = @[m1,m2,m3];
    
    
//        self.mCopyArray = mOriginArray;
//        self.mStrongArray = mOriginArray;
//        self.mWeakArray = mOriginArray;
    
    _mCopyArray = mOriginArray;
    _mStrongArray = mOriginArray;
    _mWeakArray = mOriginArray;
    
    
    NSLog(@"mOriginArray : %p, %@", mOriginArray,mOriginArray);
    NSLog(@"_mCopyArray  : %p, %@", _mCopyArray,_mCopyArray);
    NSLog(@"_mStrongArray: %p, %@", _mStrongArray,_mStrongArray);
    NSLog(@"_mWeakArray  : %p, %@", _mWeakArray,_mWeakArray);
    NSLog(@"_mWeakArray[0]  : %p, %@", mOriginArray[0],mOriginArray[0]);
    NSLog(@"引用计数:%@", [mOriginArray valueForKey: @"retainCount"]);
    NSLog(@"m1 修改前  : %p, %@", m1,m1);
    m1 = @"NEW";
    NSLog(@"m1 修改后 : %p, %@", m1,m1);
    NSLog(@"_mWeakArray[0]  : %p, %@", mOriginArray[0],mOriginArray[0]);
    NSLog(@"mOriginArray : %p, %@", mOriginArray,mOriginArray);
    NSLog(@"_mCopyArray  : %p, %@", _mCopyArray,_mCopyArray);
    NSLog(@"_mStrongArray: %p, %@", _mStrongArray,_mStrongArray);
    NSLog(@"_mWeakArray  : %p, %@", _mWeakArray,_mWeakArray);
    NSLog(@"引用计数:%@", [mOriginArray valueForKey: @"retainCount"]);

在这里插入图片描述
我们可以发现,NSArray对其赋值时,他是进行的深拷贝,上边的输出,m1虽然后边改为新值了,但是NSArray依然是老值。

在NSArray中,数组本身是浅拷贝。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章