1.KVC、KVO
2.runtime
3.block
4.GCD
5.RunLoop
1.Runloop是ios中一個(gè)非常重要的機(jī)制 ,ios系統(tǒng)底層很多模塊都通過Runloop機(jī)制來 實(shí)現(xiàn)的。例如界面更新,事件響應(yīng)等...
2.每條線程都有唯一對應(yīng)的Runloop對象,Runloop在第一次獲取時(shí)創(chuàng)建,在線程結(jié)束時(shí)銷毀.本質(zhì)就是EventLoop的do? while循環(huán)
3.ios系統(tǒng)提供了兩種Runloop:NSRunLoop和CFRunLoopRef. CFRunLoopRef是在CoreFoundation框架內(nèi)提供了C函數(shù)的API,這些API都是線程安全的. NSRunLoop是基于CFRunLoopRef的封裝,提供了面向?qū)ο蟮腁PI,不是線程安全的
4.CFRunLoopModeRef的運(yùn)行模式
kCFRunLoopDefaultMode:App的默認(rèn)運(yùn)行模式,通常主線程是在這個(gè)運(yùn)行模式下運(yùn)行
UITrackingRunLoopMode:跟蹤用戶交互事件(用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他Mode影響)
UIInitializationRunLoopMode:在剛啟動(dòng)App時(shí)第進(jìn)入的第一個(gè) Mode,啟動(dòng)完成后就不再使用
GSEventReceiveRunLoopMode:接受系統(tǒng)內(nèi)部事件,通常用不到
kCFRunLoopCommonModes:偽模式,不是一種真正的運(yùn)行模式(后邊會(huì)用到)
5.RunLoop與Autoreleasepool
RunLoop寄生于線程,一個(gè)線程只能有唯一對應(yīng)的RunLoop,但可以嵌套子RunLoops.自動(dòng)釋放池寄生于RunLoop,程序啟動(dòng)后,主線程注冊了兩個(gè)Observer監(jiān)聽RunLoop的進(jìn)出與休眠。一個(gè)最高優(yōu)先級(jí)OB檢測Entry狀態(tài),一個(gè)最低優(yōu)先級(jí)OB監(jiān)聽BeforeWaiting狀態(tài)和Exit狀態(tài).
備注:運(yùn)行循環(huán)結(jié)束前會(huì)釋放自動(dòng)釋放池,還有池子滿了也會(huì)銷毀.
五、coreData
多線程處理大量數(shù)據(jù)同步時(shí)的操作
搭建coreData多線程環(huán)境
1.NSManagedObjectContext指定并發(fā)模式
2.NSConfinementConcurrencyType:向后兼容 IOS9后廢棄
3.NSPrivateQueueConcurrencyType:私有隊(duì)列中創(chuàng)建并管理Context
4.NSMainQueueCurrencyType:Context與UI相關(guān)用這種模式
大量數(shù)據(jù)處理
大量數(shù)據(jù)意味著需要我們關(guān)注內(nèi)存占用和性能,寫代碼時(shí)需要記得一下規(guī)劃:
1.盡可能緩存需要的數(shù)據(jù),不相關(guān)的數(shù)據(jù)保持faults狀態(tài)
2.fetch時(shí)盡可能精準(zhǔn),少引入不相關(guān)的數(shù)據(jù)
3.構(gòu)建多context時(shí)盡量將同類managed object集中,最大限度減少合并需求
4.提升操作效率,對asynchronous fetch, batch update,batch delete等新特性盡可能利用
CoreData是Cocoa處理數(shù)據(jù)綁定的方案之一,提供完整的對象持久化存儲(chǔ)方案.
CoreData與多線程交互的時(shí)候每個(gè)線程必須擁有一個(gè)ManagerContext
1.每個(gè)線程使用私有managerContext共享一個(gè)PersistentStoreCoordinator
2.每個(gè)線程使用私有managerContext和私有的PersistentStoreCoordinator
推薦使用第一種,第二種消耗過多內(nèi)存
?
六、線程鎖
鎖是常用的同步工具,一段代碼在同一時(shí)間只能被一個(gè)線程訪問
1.NSLock:互斥鎖 lock unlock trylock
2.@synchronized:代碼塊
3.dispatch-semaphore_t:信號(hào)量? 支持信號(hào)通知與信號(hào)等待,每發(fā)送一個(gè)信號(hào)通知,信號(hào)+1;每發(fā)送一個(gè)信號(hào)等待信號(hào)-1
七、weak
weak實(shí)現(xiàn)原理可概括為三步
1.初始化:runtime調(diào)用objc_initweak函數(shù),初始化一個(gè)新的weak指針指向?qū)ο蟮牡刂?
2.添加引用:objc_initweak函數(shù)會(huì)調(diào)用objc_storeWeak()函數(shù)從而更新指針指向,創(chuàng)建對應(yīng)弱引用表
3.釋放:調(diào)用clearDeallocating函數(shù).clearDeallocating函數(shù)首先根據(jù)對象地址獲取所有weak指針地址的數(shù)組,然后遍歷這些數(shù)組將其中數(shù)據(jù)置為nil.最后把這個(gè)entry從weak表中刪除,最后清理對象的記錄
從實(shí)現(xiàn)中可以看出,Weak指針的使用涉及到Hash表的增刪改查,存在一定的性能開銷.Weak指針盡量用Strong,倒不是擔(dān)心形成野指針,因?yàn)槟闶褂昧薟eak指針,對象就會(huì)被加入到autoreleasepool中,可以放心使用.是為了防止一次又一次加入autoreleasepool,存在性能開銷。
八、談?wù)勀銓ψ詣?dòng)釋放池的理解
1.自動(dòng)釋放池是OC提供的一種自動(dòng)回收機(jī)制,具有延時(shí)釋放的特性,即當(dāng)我們創(chuàng)建一個(gè)對象,并把它加入自動(dòng)釋放池中,不會(huì)立即釋放,會(huì)等到一次runloop結(jié)束或者作用域超出{}或者超出【pool release】之后再被釋放
2.Runloop寄生于線程:一個(gè)線程只能有唯一對應(yīng)的Runloop,可以嵌套子Runloops
3.自動(dòng)釋放池寄生于Runloop:程序啟動(dòng)后,主線程注冊了兩個(gè)Observer監(jiān)聽Runloop的進(jìn)出與睡覺。一個(gè)最高優(yōu)先級(jí)的OB監(jiān)聽Entry狀態(tài);一個(gè)最低優(yōu)先級(jí)的OB監(jiān)聽BeforeWaiting狀態(tài)和Exit狀態(tài)
線程(創(chuàng)建)--》runloop將進(jìn)入--》最高優(yōu)先級(jí)OB創(chuàng)建釋放池--》runloop將睡--》最低優(yōu)先級(jí)的OB銷毀舊線程池創(chuàng)建新池--》runloop將退出--》最低優(yōu)先級(jí)OB銷毀新池--》線程(銷毀)
4.默認(rèn)主線程運(yùn)行循環(huán)(runloop)是開啟的,子線程的運(yùn)行循環(huán)(runloop)默認(rèn)是不開啟的,也就意味著子線程不會(huì)創(chuàng)建autoreleasepool,所以需要我們自己在子線程中創(chuàng)建自動(dòng)釋放池。
7.自動(dòng)釋放池在mrc和arc的區(qū)別
8.多層自動(dòng)釋放池嵌套的對象在哪一層釋放
最內(nèi)層釋放
9.對于block,理解,mrc和arc下有什么區(qū)別,使用注意事項(xiàng)
1.MRC環(huán)境下,在定義block為屬性時(shí),使用copy的原因,是把block從棧區(qū)拷貝到堆區(qū),因?yàn)闂^(qū)中的變量出了作用域之后就會(huì)被銷毀,無法在全局使用,所以應(yīng)該把棧區(qū)的屬性拷貝到堆區(qū)中全局共享,這樣就不會(huì)被銷毀了,在MRC手動(dòng)管理的就是堆區(qū),不需要系統(tǒng)管理,MRC環(huán)境必須使用copy把變量拷貝到全局的堆區(qū)
2.如果是ARC的環(huán)境下,就可以不使用copy修飾,因?yàn)锳RC下的屬性本來就在堆區(qū)
3.很早的時(shí)候MRC的block屬性都是在棧區(qū)的,copy之后就到堆區(qū)了
4.當(dāng)前的ARC的block屬性默認(rèn)都在堆區(qū),使用copy知識(shí)沿襲了歷史的習(xí)慣,使用strong也是沒有問題的
__block修飾符
1.在block內(nèi)部,訪問外部的變量時(shí),內(nèi)部會(huì)對外部的變量進(jìn)行一次拷貝,在block內(nèi)部操作的是拷貝之后的副本,不會(huì)影響外部的變量,這個(gè)變量的堆區(qū)。
2.在block內(nèi)部,修改外部變量,是不被允許的,非要修改要用__block
3.一旦外部的int變量(在棧區(qū))被__block標(biāo)記了,如果block內(nèi)部修改了這個(gè)變量,那么這個(gè)變量的地址會(huì)永久的被修改在堆區(qū)
4.為什么在block內(nèi)部不能修改外部的變量?
因?yàn)閎lock一般是需要傳遞給另外一個(gè)類里面,block內(nèi)部的一些變量不能存儲(chǔ)在棧區(qū),需要存在堆區(qū),不然數(shù)據(jù)就容易丟失,這就是使用__block修飾的原因,這樣傳輸數(shù)據(jù)的時(shí)候,數(shù)據(jù)就不會(huì)丟失
5.weak原理
6.如果屬性完全不加修飾詞入weak,atomic,系統(tǒng)會(huì)怎么處理
七、線程間通信
八、數(shù)據(jù)庫如何實(shí)現(xiàn)讀寫分離
九、UITableview優(yōu)化