1.NSRunLoop是消息機(jī)制的處理模式
NSRunLoop的作用在于有事情做的時(shí)候使的當(dāng)前NSRunLoop的線程工作,沒(méi)有事情做讓當(dāng)前NSRunLoop的線程休眠
2.nstimer默認(rèn)添加到當(dāng)前NSRunLoop中,也可以手動(dòng)制定添加到自己新建的NSRunLoop的中
[NSTimer?schduledTimerWithTimeInterval:?target:selector:userInfo:repeats];
此方法默認(rèn)添加到當(dāng)前NSRunLoop中
NSTimer?*timer?=?[NSTimer?timerWithTimeInterval:?invocation:repeates:];
NSTimer?*timer?=?[[NSTimer?alloc]?initWithFireDate:...];
創(chuàng)建timer??[[NSRunLoop?currentRunLoop]addTimer:timer?forMode:NSRunLoopCommonModes];
注意?timer的釋放
3.NSRunLoop就是一直在循環(huán)檢測(cè),從線程start到線程end,檢測(cè)inputsource(如點(diǎn)擊,雙擊等操作)同步事件,檢測(cè)timesource同步事件,檢測(cè)到輸入源會(huì)執(zhí)行處理函數(shù),首先會(huì)產(chǎn)生通知,corefunction向線程添加runloop?observers來(lái)監(jiān)聽(tīng)事件,意在監(jiān)聽(tīng)事件發(fā)生時(shí)來(lái)做處理。
4.runloopmode是一個(gè)集合,包括監(jiān)聽(tīng):事件源,定時(shí)器,以及需通知的runloop?observers
模式包括:
default模式:幾乎包括所有輸入源(除NSConnection)?NSDefaultRunLoopMode模式
mode模式:處理modal?panels
connection模式:處理NSConnection事件,屬于系統(tǒng)內(nèi)部,用戶(hù)基本不用
event?tracking模式:如組件拖動(dòng)輸入源?UITrackingRunLoopModes?不處理定時(shí)事件
common?modes模式:NSRunLoopCommonModes?這是一組可配置的通用模式。將input?sources與該模式關(guān)聯(lián)則同時(shí)也將input?sources與該組中的其它模式進(jìn)行了關(guān)聯(lián)。
每次運(yùn)行一個(gè)run?loop,你指定(顯式或隱式)run?loop的運(yùn)行模式。當(dāng)相應(yīng)的模式傳遞給run?loop時(shí),只有與該模式對(duì)應(yīng)的input?sources才被監(jiān)控并允許run?loop對(duì)事件進(jìn)行處理(與此類(lèi)似,也只有與該模式對(duì)應(yīng)的observers才會(huì)被通知)
例:
1).在timer與table同時(shí)執(zhí)行情況,當(dāng)拖動(dòng)table時(shí),runloop進(jìn)入U(xiǎn)ITrackingRunLoopModes模式下,不會(huì)處理定時(shí)事件,此時(shí)timer不能處理,所以此時(shí)將timer加入到NSRunLoopCommonModes模式(addTimer?forMode)
2).在scroll一個(gè)頁(yè)面時(shí)來(lái)松開(kāi),此時(shí)connection不會(huì)收到消息,由于scroll時(shí)runloop為UITrackingRunLoopModes模式,不接收輸入源,此時(shí)要修改connection的mode
[scheduleInRunLoop:[NSRunLoop?currentRunLoop]forMode:NSRunLoopCommonModes];
5.關(guān)于-(BOOL)runMode:(NSString?*)mode?beforeDate:(NSDate?*)date;方法
指定runloop模式來(lái)處理輸入源,首個(gè)輸入源或date結(jié)束退出。
暫停當(dāng)前處理的流程,轉(zhuǎn)而處理其他輸入源,當(dāng)date設(shè)置為[NSDate?distantFuture](將來(lái),基本不會(huì)到達(dá)的時(shí)間),所以除非處理其他輸入源結(jié)束,否則永不退出處理暫停的當(dāng)前處理的流程。
6.while(A){
[[NSRunLoop?currentRunLoop]?runMode:NSDefaultRunLoopMode?beforeDate:[NSDate?distantFuture]];
}
當(dāng)前A為YES時(shí),當(dāng)前runloop會(huì)一直接收處理其他輸入源,當(dāng)前流程不繼續(xù)處理,出為A為NO,當(dāng)前流程繼續(xù)
7.perform?selector在thread中被序列化執(zhí)行,這樣就緩和了許多在同一個(gè)thread中運(yùn)行多個(gè)方法所產(chǎn)生的同步問(wèn)題。perform?selector?source在運(yùn)行完selector后自動(dòng)從run?loop中移除。
當(dāng)在非main?thread中perform?selector時(shí),其thread中必須有一個(gè)激活的run?loop。對(duì)于你自己創(chuàng)建的thread而言,只有你的代碼顯式的運(yùn)行一個(gè)run?loop后該perform?selector才能得到執(zhí)行。Run?loop在當(dāng)loop運(yùn)行時(shí)處理所有已排隊(duì)的perform?selector,而不是在一個(gè)loop循環(huán)時(shí)只處理某一個(gè)perform?selector。
8.performSelector關(guān)于內(nèi)存管理的執(zhí)行原理是這樣的執(zhí)行?[self?performSelector:@selector(method1:)?withObject:self.tableLayer?afterDelay:3];?的時(shí)候,系統(tǒng)會(huì)將tableLayer的引用計(jì)數(shù)加1,執(zhí)行完這個(gè)方法時(shí),還會(huì)將tableLayer的引用計(jì)數(shù)減1,由于延遲這時(shí)tableLayer的引用計(jì)數(shù)沒(méi)有減少到0,也就導(dǎo)致了切換場(chǎng)景dealloc方法沒(méi)有被調(diào)用,出現(xiàn)了內(nèi)存泄露。
利用如下函數(shù):
[NSObject?cancelPreviousPerformRequestsWithTarget:self]
當(dāng)然你也可以一個(gè)一個(gè)得這樣用:
[NSObject?cancelPreviousPerformRequestsWithTarget:self?selector:@selector(method1:)?object:nil]
加上了這個(gè)以后,順利地執(zhí)行了dealloc方法
在touchBegan里面
[self?performSelector:@selector(longPressMethod:)?withObject:nil?afterDelay:longPressTime]
然后在end?或cancel里做判斷,如果時(shí)間不夠長(zhǎng)按的時(shí)間調(diào)用:
[NSObject?cancelPreviousPerformRequestsWithTarget:self?selector:@selector(longPressMethod:)?object:nil]
取消began里的方法
**********************************以下是我在cocoachina中看到的一份總結(jié)?轉(zhuǎn)載過(guò)來(lái)
線程實(shí)現(xiàn)的幾種方式:
1.?Operation?Objects???//?NSOperation及相關(guān)子類(lèi)
2.?*****???????????????????????????//?dispatch_async等相關(guān)函數(shù)
3.?Idle-time?notifications??//??NSNotificationQueue,低優(yōu)先級(jí)
3.?Asynchronous?functions??//?異步函數(shù)
4.?Timers??????????????????????//?NSTimer
5.?Separate?processes??//?沒(méi)用過(guò)
線程創(chuàng)建的成本:
kernel?data?structures??約1KB
Stack?space?????????????512KB(secondary?threads)
1MB(iOSmain?thread)
Creation?time???????????約90?microseconds
Run?Loop和線程的關(guān)系:
1.?主線程的run?loop默認(rèn)是啟動(dòng)的,用于接收各種輸入sources
2.?對(duì)第二線程來(lái)說(shuō),run?loop默認(rèn)是沒(méi)有啟動(dòng)的,如果你需要更多的線程交互則可以手動(dòng)配置和啟動(dòng),如果線程執(zhí)行一個(gè)長(zhǎng)時(shí)間已確定的任務(wù)則不需要。
Run?Loop什么情況下使用:
a.?使用ports?或?input?sources?和其他線程通信???//?不了解
b.?在線程中使用timers?????????????????????????????????????????????//?如果不啟動(dòng)run?loop,timer的事件是不會(huì)響應(yīng)的
c.?在Cocoa?應(yīng)用中使用performSelector...方法???//?應(yīng)該是performSelector...這種方法會(huì)啟動(dòng)一個(gè)線程并啟動(dòng)run?loop吧
d.?讓線程執(zhí)行一個(gè)周期性的任務(wù)????????????????????????????//?如果不啟動(dòng)run?loop,?線程跑完就可能被系統(tǒng)釋放了
注:timer的創(chuàng)建和釋放必須在同一線程中。
[[NSRunLoop?currentRunLoop]?addTimer:timer?forMode:NSRunLoopCommonModes];??此方法會(huì)retain?timer對(duì)象的引用計(jì)數(shù)。
何時(shí)使用Run Loop
僅當(dāng)在為你的程序創(chuàng)建輔助線程的時(shí)候,你才需要顯式運(yùn)行一個(gè) run loop。Run loop 是程序主線程基礎(chǔ)設(shè)施的關(guān)鍵部分。所以,Cocoa 和 Carbon 程序提供了代碼運(yùn) 行主程序的循環(huán)并自動(dòng)啟動(dòng) run loop。IOS 程序中 UIApplication 的 run 方法(或 Mac OS X 中的 NSApplication)作為程序啟動(dòng)步驟的一部分,它在程序正常啟動(dòng)的時(shí) 候就會(huì)啟動(dòng)程序的主循環(huán)。類(lèi)似的,RunApplicationEventLoop 函數(shù)為 Carbon 程序 啟動(dòng)主循環(huán)。如果你使用 xcode 提供的模板創(chuàng)建你的程序,那你永遠(yuǎn)不需要自己去顯 式的調(diào)用這些例程。
對(duì)于輔助線程,你需要判斷一個(gè) run loop 是否是必須的。如果是必須的,那么 你要自己配置并啟動(dòng)它。你不需要在任何情況下都去啟動(dòng)一個(gè)線程的 run loop。比 如,你使用線程來(lái)處理一個(gè)預(yù)先定義的長(zhǎng)時(shí)間運(yùn)行的任務(wù)時(shí),你應(yīng)該避免啟動(dòng) run loop。Run loop 在你要和線程有更多的交互時(shí)才需要,比如以下情況:
?使用端口或自定義輸入源來(lái)和其他線程通信
?使用線程的定時(shí)器
?Cocoa 中使用任何 performSelector...的方法
?使線程周期性工作
如果你決定在程序中使用 run loop,那么它的配置和啟動(dòng)都很簡(jiǎn)單。和所有線程 編程一樣,你需要計(jì)劃好在輔助線程退出線程的情形。讓線程自然退出往往比強(qiáng)制關(guān) 閉它更好。關(guān)于更多介紹如何配置和退出一個(gè) run loop,參閱”使用 Run Loop 對(duì)象” 的介紹。