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中,數組本身是淺拷貝。

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