首先需要定義兩個屬性:stringCopy和stringStrong纯续。如下代碼:
@interface ViewController ()
@property (nonatomic, strong) NSString *stringStrong;
@property (nonatomic, copy) NSString *stringCopy;
@end
下面首先針對不可變字符串,strong和copy的區(qū)別:
首先創(chuàng)建一個變量tempString窗看,并且將tempString的值賦值給上面所聲明的兩個屬性倦炒,如下代碼:
NSString *tempString = [NSString stringWithFormat:@"%@", @"hello, I am the original string"];
_stringCopy = tempString;
_stringStrong = tempString;
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
打印結(jié)果如下:
可以看到不管是copy還是strong修飾的字符串,指向的都是同一個內(nèi)存地址构罗,證明該賦值操作只是指針拷貝智玻,并沒有拷貝其內(nèi)容。
想給大家看一個我很白癡的舉動吊奢,我在上面代碼打印log之后纹烹,去修改了tempString的值召边,代碼如下:
tempString = @"sorry,I need change my words~";
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
看到兩個屬性值和我預(yù)想的不一樣片挂,我在想既然是指針拷貝贞盯,那么修改了tempString的值后,兩個屬性值按理應(yīng)該是跟tempString保持一致的闷愤,但是打印的結(jié)果并不是件余,結(jié)果如下:
后來,我突然反應(yīng)過來啼器,我聲明的tempString是不可變字符串旬渠,在后面給其賦值其實是使tempStirng指向了新的內(nèi)存地址镀首,而兩個屬性變量還是指向原來的內(nèi)存地址,所以修改tempString的值后更哄,tempString的值變了,內(nèi)存地址也變了觅捆,而兩個屬性變量的值沒有改變麻敌。
眼尖的讀者會發(fā)現(xiàn)我上面賦值的時候用的是_stringCopy而不是self.stringCopy,之所以這么寫术羔,是因為我想驗證下這二者之間的區(qū)別,下面我會將_stringCopy換成self.stringCopy释移,然后再執(zhí)行一下程序寥殖,代碼如下:
NSString *tempString = [NSString stringWithFormat:@"%@", @"hello, I am the original string"];
self.stringCopy = tempString;
self.stringStrong = tempString;
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
tempString = @"sorry,I need change my words~";
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
打印結(jié)果如下:
大家可以發(fā)現(xiàn)對于不可變字符串,self.stringCopy和_stringCopy得出的結(jié)果是一樣的熏纯。
下面是針對可變字符串,strong和copy的區(qū)別误窖。
將上面的不可變字符串改成NSMutableString類型的變量往扔,代碼如下:
NSMutableString *tempString = [NSMutableString stringWithFormat:@"%@", @"hello, I am the original string"];
_stringCopy = tempString;
_stringStrong = tempString;
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"_stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"_stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
NSLog(@"\n");
[tempString setString:@"sorry,I need change my words~"];
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"_stringCopy ----- %@ %p", _stringCopy, self.stringCopy);
NSLog(@"_stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
打印結(jié)果如下:
可以看出修改可變字符串的值之前臨時變量和屬性變量的值和內(nèi)存地址是一致的蝗罗;修改可變字符串tempString的值之后蝌戒,屬性變量的值也跟著變了,并且和tempString的值是一致的北苟。
如若我將_stringCopy換成self.stringCopy后再重新執(zhí)行代碼后:
NSMutableString *tempString = [NSMutableString stringWithFormat:@"%@", @"hello, I am the original string"];
self.stringCopy = tempString;
self.stringStrong = tempString;
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", self.stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
NSLog(@"\n");
[tempString setString:@"sorry,I need change my words~"];
NSLog(@"tempString:--- %@ %p", tempString,tempString);
NSLog(@"self.stringCopy ----- %@ %p", _stringCopy, self.stringCopy);
NSLog(@"self.stringStrong ----- %@ %p", self.stringStrong, self.stringStrong);
執(zhí)行結(jié)果如下:
會發(fā)現(xiàn)友鼻,修改可變字符串tempString的值之后,strong修飾的屬性變量的值和tempString的值和內(nèi)存地址都是一致的妆档,但是copy修飾的屬性變量的值沒變虫碉,即還是tempString修改之前的值。大家可能會好奇敦捧,為啥只是換了一個使用方法,為啥結(jié)果會不一樣习瑰。其實是因為通過self點語法使用屬性時济蝉,會執(zhí)行屬性的setter方法菠发,而在setter中會執(zhí)行這么一個操作:
- (void)setTempString:(NSString *)tempString {
tempString = [tempString copy]贺嫂;
///代碼塊...
}
所以對于可變字符串,如果通過下劃線_使用屬性糜俗,不會拷貝內(nèi)容,只是進行了指針拷貝曲饱;而如果是通過self點語法使用屬性變量,copy修飾的變量會拷貝內(nèi)容扩淀,從而生成新的內(nèi)存地址驻谆,但是strong修飾的變量只是進行了指針拷貝,沒有拷貝其內(nèi)容胜臊。
由上述一系列我們可以得出:
對于不可變字符串來說,不管是strong還是copy修飾的屬性變量黑忱,他們都是指向同一個對象的勒魔,即只是進行了淺拷貝(指針拷貝)。
對于可變字符串來說沥邻,strong只是進行引用計數(shù)加一的操作,并沒有對原字符串進行內(nèi)容拷貝埃跷,copy修飾的屬性變量對原字符串進行了一次深拷貝操作邮利,即執(zhí)行了內(nèi)容拷貝。