-
多線程
每個iOS應用程序都有個專門用來更新顯示UI界面、處理用戶的觸摸事件的主線程,因此不能將其他太耗時的操作放在主線程中執(zhí)行,不然會造成主線程堵塞(出現(xiàn)卡機現(xiàn)象),帶來極壞的用戶體驗。一般的解決方案就是將那些耗時的操作放到另外一個線程中去執(zhí)行,多線程編程是防止主線程堵塞,增加運行效率的最佳方法。
GCD會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務、銷毀線程)
- GCD
* GCD是Grand Central Dispatch的簡稱,它是基于C語言的。如果使用GCD,完全由系統(tǒng)管理線程,我們不需要編寫線程代碼。只需定義想要執(zhí)行的任務,然后添加到適當?shù)恼{(diào)度隊列(dispatch queue)。GCD會負責創(chuàng)建線程和調(diào)度你的任務,系統(tǒng)直接提供線程管理。
* GCD的一個重要概念是隊列,它的核心理念:將長期運行的任務拆分成多個工作單元,并將這些單元添加到dispath queue中,系統(tǒng)會為我們管理這些dispath queue,為我們在多個線程上執(zhí)行工作單元,我們不需要直接啟動和管理后臺線程。
* 1> 使用dispatch_get_current_queue函數(shù)作為調(diào)試用途,或者測試當前queue的標識。在block對象中調(diào)用這個函數(shù)會返回block提交到的queue(這個時候queue應該正在執(zhí)行中)。在block對象之外調(diào)用這個函數(shù)會返回應用的默認并發(fā)queue。
2> 使用dispatch_get_main_queue函數(shù)獲得應用主線程關(guān)聯(lián)的串行dispatch queue
3> 使用dispatch_get_global_queue來獲得共享的并發(fā)queue
* 它具有以下優(yōu)點:
1、易用: GCD比之thread跟簡單易用。由于GCD基于work unit而非像thread那樣基于運算,所以GCD可以控制諸如等待任務結(jié)束、監(jiān)視文件描述符、周期執(zhí)行代碼以及工作掛起等任務?;赽lock的血統(tǒng)導致它能極為簡單得在不同代碼作用域之間傳遞上下文。
2、效率: GCD被實現(xiàn)得如此輕量和優(yōu)雅,使得它在很多地方比之專門創(chuàng)建消耗資源的線程更實用且快速。這關(guān)系到易用性:導致GCD易用的原因有一部分在于你可以不用擔心太多的效率問題而僅僅使用它就行了。
3、性能: GCD自動根據(jù)系統(tǒng)負載來增減線程數(shù)量,這就減少了上下文切換以及增加了計算效率。
4、GCD可以將花費時間極其長的任務放到后臺線程,可以改善應用的響應性能
5、GCD 提供一個易于使用的并發(fā)模型而不僅僅只是鎖和線程,以幫助我們避開并發(fā)陷阱
6、GCD 具有在常見模式(例如單例)上用更高性能的原語優(yōu)化你的代碼的潛在能力
http://blog.csdn.net/charles91/article/details/50542940
* 并發(fā)隊列:(ConcurrentDispatch Queue)
可以讓多個任務并發(fā)(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務)
注意:并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效,因為異步函數(shù)才具備開啟新線程的能力,而同步函數(shù)只能在當前線程中執(zhí)行不具備開啟線程的能力。
dispatch_queue_t queue = dispatch_queue_create("隊列名稱", DISPATCH_QUEUE_CONCURRENT);
GCD默認已經(jīng)提供了全局的并發(fā)隊列,供整個應用使用,可以無需手動創(chuàng)建,使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);```
* 串行隊列:(SerialDispatch Queue)
讓任務一個接著一個地執(zhí)行(一個任務執(zhí)行完畢后,再執(zhí)行下一個任務)
注意:使用sync函數(shù)往當前串行隊列中添加任務,會卡住當前的串行隊列
GCD中獲得串行有2種途徑
1、使用dispatch_queue_create函數(shù)
//創(chuàng)建串行隊列(隊列類型傳遞NULL或者DISPATCH_QUEUE_SERIAL)
dispatch_queue_tqueue = dispatch_queue_create("隊列名稱",NULL);
2、主隊列(是GCD自帶的一種特殊的串行隊列)
放在主隊列中的任務,都會放到主線程中執(zhí)行
dispatch_queue_tqueue = dispatch_get_main_queue();
* dispatch_async:異步任務, 可以在新的線程中執(zhí)行任務,具備開啟新線程的能力
dispatch_async:同步任務,只能在當前線程中執(zhí)行任務,不具備開啟新線程的能力
要使用用戶隊列,我們首先得創(chuàng)建一個。調(diào)用函數(shù)dispatch_queue_create就行了。
調(diào)用dispatch_async函數(shù),傳入一個隊列和一個block。隊列會在輪到這個block執(zhí)行時執(zhí)行這個block的代碼。下面的例子是一個在后臺執(zhí)行一個巨長的任務:
* dispatch_group_t: 隊列組
應用場景:分別異步執(zhí)行2個耗時的操作,要等2個異步操作都執(zhí)行完畢后,再回到主線程執(zhí)行操作
注意:該場景,使用上面的柵欄也可解決
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//執(zhí)行1個耗時的異步操作
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
//執(zhí)行1個耗時的異步操作
});
dispatch_group_notify(group, dispatch_get_main_queue(),^{
//等前面的異步操作都執(zhí)行完畢后,回到主線程...
});
* dispatch_barrier_async:柵欄
場景:1.攔截前面的任務, 只有先添加到隊列中的任務=執(zhí)行完畢, 才會執(zhí)行柵欄添加的任務
2.如果柵欄后面還有其它的任務, 那么必須等柵欄執(zhí)行完畢才會執(zhí)行后面的其它任務
注意:1.如果想要使用柵欄, 那么就不能使用全局的并發(fā)隊列
2.如果想使用柵欄, 那么所有的任務都必須添加到同一個隊列中
* dispatch_after延時執(zhí)行。
dispatch_after 工作起來就像一個延遲版的 dispatch_async 。你依然不能控制實際的執(zhí)行時間,且一旦 dispatch_after 返回也就不能再取消它。
何時適合使用 dispatch_after ?主隊列(串行):是使用 dispatch_after 的好選擇。
* dispatch_once:
1、對于某個任務執(zhí)行一次,且只執(zhí)行一次。 dispatch_once函數(shù)有兩個參數(shù),第一個參數(shù)predicate用來保證執(zhí)行一次,第二個參數(shù)是要執(zhí)行一次的任務block。
2、dispatch_once被廣泛使用在單例、緩存等代碼中,用以保證在初始化時執(zhí)行一次某任務。
3、dispatch_once在單線程程序中毫無意義,但在多線程程序中,其低負載、高可依賴性、接口簡單等特性,贏得了廣大消費者的一致五星好評。
* dispatch_apply:
使用dispatch_apply函數(shù)能進行快速迭代遍歷,但是它和for循環(huán)又有些不同
第一個參數(shù): 需要遍歷幾次
第二個參數(shù): 決定第三個參數(shù)的block在哪個線程中執(zhí)行
第三個參數(shù): 回掉
dispatch_apply(10, 隊列queue, ^(size_tindex){
//執(zhí)行10次代碼,index順序不確定
});
*實例:拷貝文件到目標目錄中 : 快速迭代實現(xiàn)*
2. NSOpration
1、簡單說明
NSOperation的作?:配合使用NSOperation和NSOperationQueue也能實現(xiàn)多線程編程
添加操作到NSOperationQueue中,自動執(zhí)行操作,自動開啟線程
NSOperation和NSOperationQueue實現(xiàn)多線程的具體步驟:
(1)先將需要執(zhí)行的操作封裝到一個NSOperation對象中
(2)然后將NSOperation對象添加到NSOperationQueue中
(3)系統(tǒng)會?動將NSOperationQueue中的NSOperation取出來
(4)將取出的NSOperation封裝的操作放到?條新線程中執(zhí)?
2、NSOperation的子類
NSOperation是個抽象類,并不具備封裝操作的能力,必須使?它的子類
使用NSOperation?類的方式有3種:
(1)NSInvocationOperation
(2)NSBlockOperation
(3)自定義子類繼承NSOperation,實現(xiàn)內(nèi)部相應的?法
3、功能
(1)并發(fā)數(shù):同時執(zhí)?行的任務數(shù),可設置最大并發(fā)數(shù)。
(2)隊列的取消,暫停和恢復
(3)設置NSOperation在queue中的優(yōu)先級,可以改變操作的執(zhí)?優(yōu)先級
(4)NSOperation之間可以設置依賴來保證執(zhí)行順序,?如一定要讓操作A執(zhí)行完后,才能執(zhí)行操作B,可以像下面這么寫
[operationB addDependency:operationA]; // 操作B依賴于操作
(5)可以監(jiān)聽一個操作的執(zhí)行完畢
//監(jiān)聽操作的執(zhí)行完畢
operation.completionBlock=^{
//.....下載圖片后繼續(xù)進行的操作
NSLog(@"--接著下載第二張圖片--");
};
[operation setCompletionBlock:^() {
NSLog(@"執(zhí)行完畢");
}];
3. NSThread
是三種方法里面相對輕量級的,但需要管理線程的生命周期、同步、加鎖問題,這會導致一定的性能開銷
1.優(yōu)點:NSThread比其他兩種多線程方案較輕量級,更直觀地控制線程對象
2.缺點:需要自己管理線程的生命周期,線程同步。線程同步對數(shù)據(jù)的加鎖會有一定的系統(tǒng)開銷
* **造成循環(huán)引用的原因和解決方法,delloc方法不執(zhí)行**
1. NSTimer的循環(huán)引用的原因和解決方法
2. Block原理
3. 代理
4. 自定義封裝的函數(shù)中傳入了當前類
詳情見該文章:[內(nèi)存泄露控制器不釋放造成dealloc方法不執(zhí)行的原因全解](http://www.itdecent.cn/p/0b19c6cb8fc4);
* **runtime機制**
runtime是一套底層的C語言API,包含很多強大實用的C語言數(shù)據(jù)類型和C語言函數(shù),平時我們編寫的OC代碼,底層都是基于runtime實現(xiàn)的。
* 功能用途:
1.動態(tài)的遍歷一個類的所有成員變量,用于字典轉(zhuǎn)模型,歸檔解檔操作
2.可以動態(tài)的添加、修改、刪除類、方法、屬性,方法交換。
* 消息機制:方法調(diào)用稱為向?qū)ο蟀l(fā)送消息
* 一個OC方法被編譯成objc_msgSend,OC的對象通過isa找到類對象
* 類對象查找自己存儲的方法列表來找到對應的方法執(zhí)行體
* 方法執(zhí)行體執(zhí)行具體的代碼,并返回值給調(diào)用者。
* 子類調(diào)用一個方法,如果子類沒有實現(xiàn),會查找基類。
* 消息轉(zhuǎn)發(fā)(可以間接實現(xiàn)多重繼承)
當向someObject發(fā)送某消息,但runtime system在當前類和父類中都找不到對應方法的實現(xiàn)時,runtime system并不會立即報錯使程序崩潰,而是依次執(zhí)行下列步驟:
1.動態(tài)方法解析:向當前類發(fā)送 resolveInstanceMethod: 信號,檢查是否動態(tài)向該類添加了方法。(迷茫請搜索:@dynamic)
2.快速消息轉(zhuǎn)發(fā):檢查該類是否實現(xiàn)了 forwardingTargetForSelector: 方法,若實現(xiàn)了則調(diào)用這個方法。若該方法返回值對象非nil或非self,則向該返回對象重新發(fā)送消息。
3.標準消息轉(zhuǎn)發(fā):runtime發(fā)送methodSignatureForSelector:消息獲取Selector對應的方法簽名。返回值非空則通過forwardInvocation:轉(zhuǎn)發(fā)消息,返回值為空則向當前對象發(fā)送doesNotRecognizeSelector:消息,程序崩潰退出。
* **runloop機制**
Runloop是個事件循環(huán),是事件接收和分發(fā)機制的一個實現(xiàn)。內(nèi)部是一個 do-while 循環(huán)。保證程序執(zhí)行的線程不會被系統(tǒng)終止。
主線程??默認有Runloop。當自己啟動一個線程,如果只是用于處理單一的事件,則該線程在執(zhí)行完之后就退出了。
* **視頻的上傳、下載,視頻流**
* **性能、內(nèi)存優(yōu)化**
1. ARC、MRC
2. 優(yōu)化方案
詳情見[iOS 性能優(yōu)化最全總結(jié)](http://www.itdecent.cn/p/59bd44b37199);
* **oc與js通信原理**
* **MVC、MVVM**
詳情見[被誤解的MVC和被神化的MVVM](http://www.cnblogs.com/jifeng/p/5095126.html);
* **數(shù)據(jù)持久化**
1. NSUserDefaults
2. CoreData
3. 文件緩存:plist
4. 歸檔、解檔
5. FMDB
* **masonry機制 學到什么思想**
* **HTTP、TCP、Socket網(wǎng)絡通信**
TCP:面向連接、傳輸可靠(保證數(shù)據(jù)正確性,保證數(shù)據(jù)順序)、用于傳輸大量數(shù)據(jù)(流模式)、速度慢,建立連接需要開銷較多(時間,系統(tǒng)資源)。
UDP:面向非連接、傳輸不可靠、用于傳輸少量數(shù)據(jù)(數(shù)據(jù)包模式)、速度快。
TCP是一種流模式的協(xié)議,UDP是一種數(shù)據(jù)報模式的協(xié)議。
Socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API),通過Socket,我們才能使用TCP/IP協(xié)議。
詳情見[socket詳解](http://www.itdecent.cn/p/3e4f3de18e3b#)
* **設計模式**
(一)代理模式
應用場景:當一個類的某些功能需要由別的類來實現(xiàn),但是又不確定具體會是哪個類實現(xiàn)。
優(yōu)勢:解耦合
敏捷原則:開放-封閉原則
實例:tableview的 數(shù)據(jù)源delegate,通過和protocol的配合,完成委托訴求。
列表row個數(shù)delegate
自定義的delegate
(二)觀察者模式
應用場景:一般為model層對,controller和view進行的通知方式,不關(guān)心誰去接收,只負責發(fā)布信息。
優(yōu)勢:解耦合
敏捷原則:接口隔離原則,開放-封閉原則
實例:Notification通知中心,注冊通知中心,任何位置可以發(fā)送消息,注冊觀察者的對象可以接收。
kvo,鍵值對改變通知的觀察者,平時基本沒用過。
(三)MVC模式
應用場景:是一中非常古老的設計模式,通過數(shù)據(jù)模型,控制器邏輯,視圖展示將應用程序進行邏輯劃分。
優(yōu)勢:使系統(tǒng),層次清晰,職責分明,易于維護
敏捷原則:對擴展開放-對修改封閉
實例:model-即數(shù)據(jù)模型,view-視圖展示,controller進行UI展現(xiàn)和數(shù)據(jù)交互的邏輯控制。
(四)單例模式
應用場景:確保程序運行期某個類,只有一份實例,用于進行資源共享控制。
優(yōu)勢:使用簡單,延時求值,易于跨模塊
敏捷原則:單一職責原則
實例:[UIApplication sharedApplication]。
注意事項:確保使用者只能通過 getInstance方法才能獲得,單例類的唯一實例。
java,C++中使其沒有公有構(gòu)造函數(shù),私有化并覆蓋其構(gòu)造函數(shù)。
object c中,重寫allocWithZone方法,保證即使用戶用 alloc方法直接創(chuàng)建單例類的實例,
返回的也只是此單例類的唯一靜態(tài)變量。
(五)策略模式
應用場景:定義算法族,封裝起來,使他們之間可以相互替換。
優(yōu)勢:使算法的變化獨立于使用算法的用戶
敏捷原則:接口隔離原則;多用組合,少用繼承;針對接口編程,而非實現(xiàn)。
實例:排序算法,NSArray的sortedArrayUsingSelector;經(jīng)典的鴨子會叫,會飛案例。
注意事項:1,剝離類中易于變化的行為,通過組合的方式嵌入抽象基類
2,變化的行為抽象基類為,所有可變變化的父類
3,用戶類的最終實例,通過注入行為實例的方式,設定易變行為
防止了繼承行為方式,導致無關(guān)行為污染子類。完成了策略封裝和可替換性。
(六)工廠模式
應用場景:工廠方式創(chuàng)建類的實例,多與proxy模式配合,創(chuàng)建可替換代理類。
優(yōu)勢:易于替換,面向抽象編程,application只與抽象工廠和易變類的共性抽象類發(fā)生調(diào)用關(guān)系。
敏捷原則:DIP依賴倒置原則
實例:項目部署環(huán)境中依賴多個不同類型的數(shù)據(jù)庫時,需要使用工廠配合proxy完成易用性替換
注意事項:項目初期,軟件結(jié)構(gòu)和需求都沒有穩(wěn)定下來時,不建議使用此模式,因為其劣勢也很明顯,
增 加了代碼的復雜度,增加了調(diào)用層次,增加了內(nèi)存負擔。所以要注意防止模式的濫用。
* **UI的渲染機制和動畫原理**
* **第三方庫的實現(xiàn)原理**
1. MJRefresh
2. JsonModel
3. MJExtention
4. SDWebimage