使用assign、copy、strong、weak、retain的區別在于:
- 是否開辟新的內存
- 對象的引用計數是否增加
assign和weak
- assign主要用于修飾基本數據類型,進行賦值操作,不更改引用計數; 因為基本數據類型是分配在棧上的,由系統分配和釋放,不會造成野指針
- weak修飾OC對象類型,weak表示指向但不擁有該對象;修飾的對象在釋放后,指針地址也會被置為nil,是一種弱引用,不會造成野指針
delegate為什么要用weak修飾
在ARC環境下,為了避免循環引用,一般會將delegate屬性用weak修飾,被修飾的delegate屬性引用計數不會增加,代表一種弱引用,不持有關系,而且weak修飾的對象內存被釋放后,指針地址也會被置為nil;在MRC下使用assign修飾,并且手動將delegate屬性置為nil
strong
strong表示指向并擁有該對象,其修飾的對象引用計數會增加1。該對象只要引用計數不為0就不會被銷毀,當然強行將其設為nil可以銷毀它
在MRC下,使用retain,等同于ARC下的strong
Objective-C 中,基本數據類型的默認關鍵字是atomic, readwrite, assign;普通屬性的默認關鍵字是atomic, readwrite, strong。
ARC下 對象何時被釋放
本質: 對象的引用計數為0時,自動釋放
表象: 沒有強指針指向這個對象,對象就被立即回收
什么情況下叫做對象沒有強指針指向:
- 指向對象的強指針被回收(比如 強指針式局部變量)
- 指向對象的強指針被賦值為nil
引用計數是作用在指針上還是實際對象的內存?
在.m文件中 如果對象沒有初始化而查看引用計數會導致崩潰,初始化之后就不會了,可以得出引用計數是針對指針所指向的對象的而不是指針本身
可變變量中,使用copy修飾,是重新開辟內存,其實就是對所修飾的對象深拷貝,strong、weak、assign三者不開辟內存,指針指向原內存地址;strong指向后該對象的內存引用計數增加1,而weak、assign不會。weak、assign會在引用計數為0時值為空,并且weak會將內存值設為nil(內存被回收,對象指針銷毀),而assign可能會造成其內存已不可用,但其指針仍存在,此時調用其指針對象,會崩潰。
不可變變量中,因為值本身不可被改變,copy沒必要開辟一塊內存存放和原來一樣的值,所以內存管理系統默認都是淺拷貝。 與可變變量一樣,如weak修飾的變量同樣會在內存引用計數為0時變為nil
NSString為什么使用copy修飾?
- 如果賦值源是不可變字符串,則使用strong、copy修飾,結果是一樣的,因為不可變字符串本身不可變,即使修改了源字符串的值,其會新開辟一塊內存存儲,也不會影響這個源字符串所賦值的新字符串對象。
- 如果賦值源是可變字符串,則若想修改源字符串時不影響被賦值新生成的字符串的值,就需要用copy; 因為若使用strong,指針會指向原對象,引用計數+1,這個可變的源字符串修改的話,會影響新生成的這個字符串(不論是可變還是不可變的);若使用copy,相當于深拷貝,會生成新的內存地址和指針地址,與原字符串沒有關系,修改其值不影響新生成的這個字符串(copy后的對象肯定是不可變字符串)
@property (nonatomic, strong) NSString *strongStr;
NSMutableString *originStr = [NSMutableString stringWithString:@"This is Hi"];
self.strongStr = originStr;
NSLog(@"%@ %p %p", originStr, originStr, &originStr);
NSLog(@"%@ %p %p", self.strongStr, self.strongStr, &_strongStr);
[originStr appendString:@" 嗯嗯"];
NSLog(@"%@ %p %p", originStr, originStr, &originStr);
NSLog(@"%@ %p %p", self.strongStr, self.strongStr, &_strongStr);
結果:
This is Hi 0x600002c93930 0x7ff7bc382588
This is Hi 0x600002c93930 0x7fccf4818d90
This is Hi 嗯嗯 0x600002c93930 0x7ff7bc382588
This is Hi 嗯嗯 0x600002c93930 0x7fccf4818d90
@property (nonatomic, copy) NSString *copyedStr;
NSMutableString *originStr = [NSMutableString stringWithString:@"This is Hi"];
self.copyedStr = originStr;
NSLog(@"%@ %p %p", originStr, originStr, &originStr);
NSLog(@"%@ %p %p", self.copyedStr, self.copyedStr, &_copyedStr);
[originStr appendString:@" 嗯嗯"];
NSLog(@"%@ %p %p", originStr, originStr, &originStr);
NSLog(@"%@ %p %p", self.copyedStr, self.copyedStr, &_copyedStr);
結果:
This is Hi 0x600000dd42d0 0x7ff7b20c5588
This is Hi 0x6000003e4980 0x7f80c91171a8
This is Hi 嗯嗯 0x600000dd42d0 0x7ff7b20c5588
This is Hi 0x6000003e4980 0x7f80c91171a8
參考:
iOS-使用strong,copy,assign,weak 修飾變量的異同點
iOS中copy,strong,retain,weak和assign的區別