一. NSString
大多數(shù)對于NSString類型的對象作為屬性都用的是copy,根本原因:
因為通常不想新的string會影響已有的string
NSMutableString *name = [NSMutableString stringWithString:@"123"];
NSString *name1 = name;
[name appendString:@"*"];
我修改name的值,name1卻改變了采用Copy的原因
實現(xiàn)新的string不影響已有的string
原理:
1) 如果你傳進來的是一個不可變字符串,我copy過后,系統(tǒng)是不會重新分 配內(nèi)存的,而且因為不可變字符串的特性,我對新的string修改不會影響已有的string
2) 如果傳進來的是一個可變字符串,我copy過后,系統(tǒng)會重新分配一塊內(nèi)存,因為是新的string和已有的string指向的不是同一塊內(nèi)存,所以不管更改誰都不會對彼此產(chǎn)生影響
示例:
定義一個Person類,分別采用copy和reatin修飾@property修飾的name屬性
為什么不采用retain
不管我傳進來的是可變還是不可變字符串,新string都會對已有的string產(chǎn)生影響
1)retain就相當于直接復制,這種情況新的string和已有的string指向的同一塊內(nèi)存
2)因為指向的是同一塊內(nèi)存,所以不管更改誰都會對彼此造成影響
延展:
不只是NSString,其他的不可變的類,NSArray,NSDictionary,NSSet等,都是推薦采用copy
基本數(shù)據(jù)類型用assing修飾
不區(qū)分可變不可變的對象采用retain
二.類目(category)的基本概念和用法
1、封裝是面向?qū)ο蟮囊粋€特征,OC也不意外,但有時候我們會碰到這樣一種情況,比如我封裝了一個類,不想再動它了,可是隨著程序功能的增加,需要在哪個類中增加一個小小的方法,這是我們就不必再那個類中做修改或者在定義一個子類,只需要在用到那個方法時隨手添加一個該類的類目即可
1) 在類目定義的方法,會成為原始類的一部分,與其他方法的調(diào)用沒有區(qū)別
2) 通過給父類定義類目方法,其子類也會繼承這些方法,如果子類添加類目方法,父類則不會擁有子類的類目方法
2、類目的應用和局限
1)應用
對現(xiàn)有類進行擴展:
比如,可以擴展Cocoa Touch框架中的類,你在類目中增加的方法會被子類所繼承,而且在運行時跟其他的方法沒有區(qū)別
作為子類的替代手段:
不需要定義和使用一個子類,可以通過類目直接向已有的類增加方法
對類中的方法歸類:
利用category把龐大的類劃分為小塊分別進行開發(fā),從而更好的對類中的方法進行更新和維護
2)局限性
無法向類目中,添加新的實例變量,類目中沒有位置來容納實例變量,如果想增加類的實例變量,只能通過定義子類的方式
在類目中一般不要覆蓋現(xiàn)有類的方法
、延展基本概念和用法
類的延展就如同是"匿名"的類目,延展中聲明的方法在類本身的@implementation和它對應的@end之間實現(xiàn),類有時需要方法方法只有自己所見,我們可以通過延展的方式定義類的私有方法
//延展
@interface Person ()
- (void)privateMethod;
@end
三、示例
創(chuàng)建一個MachinePerson類,讓這個機器人能夠說話,在不改變原類的基礎上讓這個機器人會跳舞
給NSArray添加一個類目,讓NSArray能夠?qū)nt型各位上的數(shù)放到一個數(shù)組中
四、引用計數(shù)器和對象所有權的基本概念
1、引用計數(shù)器
每個對象都會有一個引用計數(shù)器,當引用計數(shù)器為0是,系統(tǒng)就會將這個對象給釋放
2、對象所有權
當一個所有者(owner,其本身可以是任何一個OC對象)做了以下某個動作時,它就擁有了對一個對象的所有權
1)alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
2) 如果沒有創(chuàng)建對象,而是將對象保留使用,同樣擁有該對象的所有權
retain
3) 如果你擁有了某個對象的所有權,在不需要某一個對象時,需要釋放他們
release autorelease
3.案例
1) 假設在main函數(shù)主程序中,不小心想powerPC實例對象發(fā)送了release消息,即powerPC實例銷毀了,但apple實例可能仍然在某個地方在使用powerPC實例,那么你的程序就會crash掉。
2) 我們知道2005年后,蘋果的CPU轉向了intel的懷抱,因此,我們需要將CPU改為intel的CPU
4.詳解delloc方法
什么時候調(diào)用
當對象的引用計數(shù)器為0時,系統(tǒng)會自動調(diào)用delloc方法,回收內(nèi)存
為什么要調(diào)用父類的dealloc方法
子類的某些實例是繼承自父類的,因此我們需要調(diào)用父類的delloc,釋放父類擁有的這些對象
調(diào)用順序
1)釋放子類中的對象
2)釋放父類中所擁有的實例
5.案例
創(chuàng)建一個Vehicle類,以及Vehicle類的子類Car類,Vehicle類擁有一個實例變量_name,以及一個初始化名字的實例方法。
Car類自身擁有一個V6渦輪增加引擎。
6.總結
該如何持有對象
1)初始化方法
2)直接向?qū)ο蟀l(fā)送retain消息,持有dealloc方法釋放該對象
3)
五、點語法的內(nèi)存管理
1、賦值:
1)assign:直接賦值,默認
2)retain:賦值,并保留對象
3)copy:拷貝對象
2、讀寫性
1)readwrite:生成getter、setter方法,默認是readwrite
2) readonly:生成getter方法
3、原子性
1)atomic:多線程環(huán)境下, 存在線程保護,默認
2)nonatomic:多線程環(huán)境下,不存在線程保
六、ASSIGN、RETAIN與COPY的區(qū)別
1、assign
直接賦值,只是一個別名而已。
2、retain
保留的這個對象,兩個對象指向了同一個位置。
3、copy
開辟了一個新的內(nèi)存空間,分別指向了不同的內(nèi)存位置,引用計數(shù)分別為1,與之前的對象完全脫離關系。這里我們尤其需要注意,某些時候copy的
作用相當于retain
七、自動釋放池
1、基本概念
cocoa有一個自動釋放池的概念,顧名思義,他是可以存放一些實體的集合,在這個自動釋放池中的對象,是能夠被自動釋放的
NSObject類提供了一個autorelease消息,當我們向一個對象發(fā)送autorelease消息時,這個對象就被放入了自動釋放池
2、 自動釋放池的銷毀時間
當我們想一個對象發(fā)送了autorelease消息是,當自動釋放池銷毀時,會對池中的每個對象發(fā)送一條release消息,以此釋放他們
3、創(chuàng)建自動釋放池
ios5.0 后寫法
@autoreleasepool {}
ios5.0 之前寫法
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[pool release];
4、示例
創(chuàng)建一個Person類,創(chuàng)建一個Person類的實例jack,將jack加入自動釋放池,即向他發(fā)送一條autorelease消息,查看它的生命周期是怎樣的。
完成第一點內(nèi)容后,我們在向jack實例發(fā)送一條retain消息。查看它的引用計數(shù)和生命周期是如何的。
八、內(nèi)存管理總結
1、當你使用new, alloc或copy方法創(chuàng)建一個對象時,該對象的引用計數(shù)器為1。當不再使用該對象時,你要負責向該對象發(fā)送一條release或者autorelease消息,這樣,該對象將在其使用壽命結束時被銷毀
2、你通過任何其他方法獲得一個對象時,則假設該對象的引用計數(shù)為1,而且已經(jīng)被設置為自動釋放,你不需要執(zhí)行任何方法來釋放該對象。如果你打算在一段時間內(nèi)擁有該對象,則需要保留它并確保在操作完成時釋放它。
3、如果你保留了某個對象,你需要釋放或自動釋放該對象,必須保持retain方法和release方法的使用次數(shù)相等。
4、除了alloc、new或copy之外的方法創(chuàng)建的對象都被聲明了autorelease。誰retain,誰release。只要你調(diào)用了retain,無論這個對象是如何生成的,你都要調(diào)用release。有時候你的代碼中明明沒有retain
5、大道至簡
如果創(chuàng)建一個對象使用了alloc、copy[mutable]、retain,那么你就有義務向這個
對象發(fā)送一條release或者autorelease消息。
九、內(nèi)存管理的兩種方式
1. ARC 自動管理
iOS5.0的編譯特性,它只允許用戶開辟內(nèi)存空間,不去釋放空間,編譯器幫程序員默認加了釋放的代碼
2. MRC 手動管理
內(nèi)存的開辟和釋放都由程序代碼進行控制,相對垃圾回收來說,對內(nèi)存的控制更加靈活,可以在自己需要的釋放的時候及時釋放,對程序員的要求較高,程序員要熟悉內(nèi)存管理機制。
內(nèi)存管理機制:引用計數(shù)器
十、ARC和垃圾回收機制
1、垃圾回收機制
程序只需要開辟內(nèi)存空間,不需要用代碼顯示的釋放,系統(tǒng)來判斷哪些空間不再被使用,并回收這些內(nèi)存空間,以便再次分配,整個回收的過程不需要寫任何代碼,由系統(tǒng)自動完成垃圾回收
2、與java/net語言相同,oc2.0以后,也提供了垃圾回收機制,但在iOS移動終端設備中,并不支持垃圾回收機制(取決于終端設備的性能),因此iPhone并不能對內(nèi)存進行自動垃圾回收處理(中間模式autorelease)
3、垃圾回收機制并不是ARC,ARC也是需要管理內(nèi)存的,只不過是隱式的管理內(nèi)存,編譯器會在適當?shù)牡胤阶詣硬迦雛etain.release和autorelease消息
十一、協(xié)議(protocol)的基本概念
1、協(xié)議的聲明看起來比較類似一個類的接口文件,不同的是協(xié)議沒有父類也不能定義實例變量。
2、協(xié)議是一種特殊的程序設計結構,用于聲明專門被別的類實現(xiàn)的方法,協(xié)議在以下場合非常有用:
1)需要由別的類實現(xiàn)的方法
2)聲明未知類的接口
3)兩個雷之間的通信
3、協(xié)議的基本特點
1)協(xié)議可以被任何類實現(xiàn)方法,協(xié)議本身不是類,他是定義了一個其他類可實現(xiàn)的接口,類目也可以采用協(xié)議
2)協(xié)議的關鍵字
@required:表示必須強制實現(xiàn)的方法
@optional:表示可以有選擇性的實現(xiàn)方法
3)實現(xiàn)的聲明與實現(xiàn)
/* 協(xié)議的聲明 */
@protocol HelloProtocol <NSObject>
@optional
- (void)optionalMethod1;
- (void)optionalMethod2;
@required
- (void)requiredMethod1;
@end
/* 協(xié)議的實現(xiàn) */
@implementation Person
- (void)requiredMethod1 {
} // 實現(xiàn)了該協(xié)議中的方法,且方法必須實現(xiàn)
- (void)optionalMethod1 {
} // 實現(xiàn)了該協(xié)議中的方法,可以選擇不實現(xiàn)
@end
/* 采用了該協(xié)議 */
@interface Person : NSObject
<HelloProtocol, OtherProtocol>
@end
十二、委托設計模式
1、指一個對象提供機會對另一個對象中的行為發(fā)生變化時做出的反應
如:當將一顆石子(對象1)丟入水中(行為發(fā)生變化,之前可能在你的手中)時,水面(對象2)泛起波紋(做出的反應)
2、基本思想:
兩個對象協(xié)同解決問題,通常用于對象之間的通信
3、基本特點:
1)簡化了對象的行為,最小化了對象之間的耦合度
2)使用代理,一般來說無需子類化
3)簡化了應用程序開發(fā),既容易實現(xiàn),又靈活
十三、 示例:中介找房
1、假設有一個Jack的人(Person),他想租一套公寓(Apartment),由于他工作繁忙(或者其他原因),沒有時間(或者自身沒有能力)去租房。因此,他委托中介公司(Agent)幫他尋找房源,找到合適的房源告知Jack。
2、補充
1)定時器
一旦創(chuàng)建了一個定時器對象(NSTimer實例),他可以按照一定時間的間隔,將指定消息發(fā)送到目標對象,并更新某個對象的行為,你可以選擇在未來的某個時候?qū)⑺?開啟",或者將它停止乃至銷毀。
2)NSRunloop
一個runloop就是一個事件處理的循環(huán),用來不斷的調(diào)度工作以及處理輸入事件,使用runloop的目的是讓你的線程在有工作的時候忙于工作,而沒有工作的時候處于休眠狀態(tài)
在我們的應用程序中,不需要創(chuàng)建NSRunloop對象,因為,在我們的主線程中(包含其他子線程)系統(tǒng)會自動穿件NSRunloop對象,如果需要訪問當前線程中的runloop,你可以通過類方法『currentRunloop』獲取到