- Objective-C變量前面加"_"是什么意思?
- 聲明的property如果沒(méi)有指定synthesize犀忱,就會(huì)自動(dòng)聲明_開頭的實(shí)例變量。
- 假如你聲明了一個(gè)@property(nonatomic, copy) NSString *name;通過(guò)_name進(jìn)行存取不會(huì)調(diào)用setter/getter方法,聲明的copy也不會(huì)起作用褪储,self.name會(huì)調(diào)用setter/getter方法蟀架,copy起作用瓣赂。
- @synthesize name = name;就不會(huì)生成_name片拍,取而代之的是name煌集。
- @property內(nèi)存管理策略
-
非ARC
- copy:只用于NSString/block。
- retain:除NSString/block以外的OC對(duì)象捌省。
- assign:基本數(shù)據(jù)類型苫纤、枚舉、結(jié)構(gòu)體(非OC對(duì)象),當(dāng)2個(gè)對(duì)象相互引用卷拘, 一端用retain喊废,一端用assign。
-
ARC
- copy:只用于NSString/block栗弟。
- strong:用于除NSString/block以外的對(duì)象污筷。
- weak:當(dāng)兩個(gè)對(duì)象互相飲用,一端用strong乍赫,一端用weak瓣蛀。
- assign:基本數(shù)據(jù)類型、枚舉雷厂、結(jié)構(gòu)體(非OC對(duì)象)惋增。
-
- copy/mutableCopy
- 利用原對(duì)象產(chǎn)生一個(gè)副本對(duì)象(副本對(duì)象中的內(nèi)容和原對(duì)象內(nèi)容一致),修改原對(duì)象的屬性和行為不會(huì)影響副本對(duì)象改鲫,修改副本對(duì)象不會(huì)影響原對(duì)象诈皿。
- 一般情況下copy/mutableCopy操作會(huì)生成一個(gè)新的對(duì)象,但是不可變對(duì)象通過(guò)copy不會(huì)生成新對(duì)象钩杰。
- 產(chǎn)生新對(duì)象的原因
1. 修改原對(duì)象不會(huì)影響副本對(duì)象纫塌,修改副本對(duì)象不會(huì)影響原對(duì)象。
2. 不可變對(duì)象通過(guò)mutableCopy生成可變對(duì)象讲弄,所以必須生成新對(duì)象(可變對(duì)象通過(guò)copy生成不可變對(duì)象同理)措左。
3. 可變對(duì)象通過(guò)mutableCopy生成可變對(duì)象,當(dāng)修改原/副本對(duì)象的時(shí)候不能相互影響所以要生成新對(duì)象避除。
4. 不可變對(duì)象通過(guò)copy生成不可變對(duì)象怎披,因?yàn)閮蓚€(gè)對(duì)象是都不能修改的,所以不會(huì)生成新對(duì)象(oc的內(nèi)存優(yōu)化)瓶摆。- 正因?yàn)閏opy有時(shí)會(huì)生成新對(duì)象凉逛,有時(shí)不會(huì)生成新對(duì)象,所以就出現(xiàn)了淺拷貝與深拷貝
- 淺拷貝:沒(méi)有生成新對(duì)象群井,本質(zhì)就是指針拷貝状飞。
- 注意:
原對(duì)象引用計(jì)數(shù)+1(相當(dāng)于進(jìn)行retain操作)。
- 注意:
- 深拷貝:生成新對(duì)象书斜,本質(zhì)就是創(chuàng)建了一個(gè)新對(duì)象诬辈。
- 注意:原對(duì)象引用計(jì)數(shù)不變。
- 淺拷貝:沒(méi)有生成新對(duì)象群井,本質(zhì)就是指針拷貝状飞。
- 正因?yàn)閏opy有時(shí)會(huì)生成新對(duì)象凉逛,有時(shí)不會(huì)生成新對(duì)象,所以就出現(xiàn)了淺拷貝與深拷貝
- 如果想令自己的類支持拷貝操作就要實(shí)現(xiàn)NSCopying或NSMutableCopying協(xié)議荐吉。如果自定義的對(duì)象分為可變和不可變兩個(gè)版本焙糟,就要同時(shí)實(shí)現(xiàn)NSCopying和NSMutableCopying協(xié)議。
-
NSCopying協(xié)議中只有一個(gè)方法(生成不可變對(duì)象)
- (id)copyWithZone:(nullable NSZone *)zone;
實(shí)現(xiàn):
//Person.h @property (nonatomic, assign) int age; @property (nonatomic, copy) NSString *name; //Person.m - (id)copyWithZone:(NSZone *)zone { // 1.創(chuàng)建一個(gè)新的對(duì)象 Person *p = [[[self class] allocWithZone:zone] init]; // 2.設(shè)置當(dāng)前對(duì)象的內(nèi)容給新的對(duì)象 p.age = _age; p.name = _name; // 3.返回新的對(duì)象 return p; }
-
NSMutableCopying協(xié)議中只有一個(gè)方法(生成可變對(duì)象)
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
實(shí)現(xiàn):
//Person.h @property (nonatomic, assign) int age; @property (nonatomic, copy) NSString *name; //Person.m - (id)mutableCopyWithZone:(NSZone *)zone { // 1.創(chuàng)建一個(gè)新的對(duì)象 Person *p = [[[self class] allocWithZone:zone] init]; // 2.設(shè)置當(dāng)前對(duì)象的內(nèi)容給新的對(duì)象 p.age = _age; p.name = _name; // 3.返回新的對(duì)象 return p; }
-
舉例
[NSArray mutableCopy] -> NSMutableArray [NSMutableArray copy] -> NSArray
-
淺拷貝:只拷貝容器對(duì)象本身样屠,而不復(fù)制其中的數(shù)據(jù)穿撮。
//Person.h @property (nonatomic, assign) int age; @property (nonatomic, copy) NSString *name; //Person.m - (id)copyWithZone:(NSZone *)zone { // 1.創(chuàng)建一個(gè)新的對(duì)象 Person *p = self; // 2.返回新的對(duì)象 return p; }
-
深拷貝:在拷貝對(duì)象自身的時(shí)候缺脉,將底層數(shù)據(jù)也復(fù)制過(guò)去。
//Person.h @property (nonatomic, assign) int age; @property (nonatomic, copy) NSString *name; //Person.m - (id)deepCopy { // 1.創(chuàng)建一個(gè)新的對(duì)象 Person *p = [[[self class] allocWithZone:zone] init]; // 2.設(shè)置當(dāng)前對(duì)象的內(nèi)容給新的對(duì)象 p.age = _age; p.name = _name; // 3.返回新的對(duì)象 return p; }
復(fù)制對(duì)象的時(shí)候一般執(zhí)行淺拷貝悦穿。
如果你的對(duì)象需要深拷貝攻礼,應(yīng)該考慮專門執(zhí)行深拷貝的方法。
字符串屬性都要使用copy咧党。(防止外界修改內(nèi)部數(shù)據(jù))
-
使用copy保存block秘蛔,這樣可以保住block中使用的外界對(duì)象,避免以后調(diào)用block的時(shí)候傍衡,對(duì)象已經(jīng)被外界釋放深员。(Block_release(blcok),MRC中使用蛙埂,釋放block倦畅,并且block中的對(duì)象也可以接收到release消息)
- 注意:copy block之后會(huì)產(chǎn)生循環(huán)引用(對(duì)象中的block又用到了對(duì)象自己),為了避免內(nèi)存泄漏應(yīng)該講對(duì)象修飾為__block.
-
子類會(huì)繼承父類的協(xié)議绣的,當(dāng)父類實(shí)現(xiàn)了copy的方法叠赐,子類也就相應(yīng)的實(shí)現(xiàn)了。但是如果子類有新的屬性屡江,那么必須在子類中重寫copyWithZone方法, 在該方法中先調(diào)用父類創(chuàng)建副本設(shè)置值, 然后再設(shè)置子類特有的值芭概。
- 舉例(Son為上文中Person的子類)
Son.h @property (nonatomic, assign) double height; Son.m - (id)copyWithZone:(NSZone *)zone { // 1.創(chuàng)建一個(gè)新的對(duì)象 id obj = [super copyWithZone:zone]; // 2.設(shè)置新對(duì)象的數(shù)據(jù) [obj setHeight:_height]; // 3.返回新對(duì)象 return obj; } ```
-
-
集合((可變)數(shù)組、(可變)字典惩嘉、NSSet)對(duì)象的內(nèi)存管理:
- 將一個(gè)對(duì)象添加到一個(gè)集合中罢洲,集合會(huì)對(duì)對(duì)象進(jìn)行一次retain操作(引用計(jì)數(shù)加一)。
- 當(dāng)集合釋放對(duì)象之后會(huì)給集合中所有的對(duì)象發(fā)送release消息(引用計(jì)數(shù)減一)文黎。
- 當(dāng)集合移除一個(gè)對(duì)象之后惹苗,會(huì)給這個(gè)對(duì)象發(fā)送release消息(引用計(jì)數(shù)減一)。
-
block默認(rèn)存儲(chǔ)在棧中耸峭,棧中的block訪問(wèn)外界對(duì)象桩蓉,不會(huì)對(duì)外界對(duì)象進(jìn)行retian操作。如果block在堆中劳闹,并且訪問(wèn)了外界對(duì)象院究,就會(huì)對(duì)外界對(duì)象進(jìn)行一次retain操作。
//將block轉(zhuǎn)移到堆中 Block_copy(block);