国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > iOS > 正文

ios 中runtime和runloop 的區(qū)別

2019-11-09 14:43:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

       Runloop是事件接收和分發(fā)機(jī)制的一個(gè)實(shí)現(xiàn)。

       Runloop提供了一種異步執(zhí)行代碼的機(jī)制,不能并行執(zhí)行任務(wù)。

       在主隊(duì)列中,Main RunLoop直接配合任務(wù)的執(zhí)行,負(fù)責(zé)處理UI事件、定時(shí)器以及其他內(nèi)核相關(guān)事件。

(1).RunLoop的主要目的:

       保證程序執(zhí)行的線程不會(huì)被系統(tǒng)終止。    

(2).什么時(shí)候使用Runloop ?

       當(dāng)需要和該線程進(jìn)行交互的時(shí)候才會(huì)使用Runloop.

       每一個(gè)線程都有其對(duì)應(yīng)的RunLoop,但是默認(rèn)非主線程的RunLoop是沒(méi)有運(yùn)行的,需要為RunLoop添加至少一個(gè)事件源,然后去run它。

       一般情況下我們是沒(méi)有必要去啟用線程的RunLoop的,除非你在一個(gè)單獨(dú)的線程中需要長(zhǎng)久的檢測(cè)某個(gè)事件。

       主線程默認(rèn)有Runloop。當(dāng)自己?jiǎn)?dòng)一個(gè)線程,如果只是用于處理單一的事件,則該線程在執(zhí)行完之后就退出了。所以當(dāng)我們需要讓該線程監(jiān)聽(tīng)某項(xiàng)事務(wù)時(shí),就得讓線程一直不退出,runloop就是這么一個(gè)循環(huán),沒(méi)有事件的時(shí)候,一直卡著,有事件來(lái)臨了,執(zhí)行其對(duì)應(yīng)的函數(shù)。

       RunLoop,正如其名所示,是線程進(jìn)入和被線程用來(lái)相應(yīng)事件以及調(diào)用事件處理函數(shù)的地方.需要在代碼中使用控制語(yǔ)句實(shí)現(xiàn)RunLoop的循環(huán),也就是說(shuō),需要代碼提供while或者for循環(huán)來(lái)驅(qū)動(dòng)RunLoop.

       在這個(gè)循環(huán)中,使用一個(gè)runLoop對(duì)象[NSRunloop currentRunloop]執(zhí)行接收消息,調(diào)用對(duì)應(yīng)的處理函數(shù).

        Runloop接收兩種源事件:input sources和timer sources。

       input sources 傳遞異步事件,通常是來(lái)自其他線程和不同的程序中的消息;

       timer sources(定時(shí)器) 傳遞同步事件(重復(fù)執(zhí)行或者在特定時(shí)間上觸發(fā))。

       除了處理input sources,Runloop 也會(huì)產(chǎn)生一些關(guān)于本身行為的notificaiton。注冊(cè)成為Runloop的observer,可以接收到這些notification,做一些額外的處理。(使用CoreFoundation來(lái)成為runloop的observer)。

Runloop工作的特點(diǎn):

       1>當(dāng)有時(shí)間發(fā)生時(shí),Runloop會(huì)根據(jù)具體的事件類型通知應(yīng)用程序作出相應(yīng);

       2>當(dāng)沒(méi)有事件發(fā)生時(shí),Runloop會(huì)進(jìn)入休眠狀態(tài),從而達(dá)到省電的目的;

       3>當(dāng)事件再次發(fā)生時(shí),Runloop會(huì)被重新喚醒,處理事件.

提示:一般在開(kāi)發(fā)中很少會(huì)主動(dòng)創(chuàng)建Runloop,而通常會(huì)把事件添加到Runloop中.

二.Runtime:

        RunTime簡(jiǎn)稱運(yùn)行時(shí)。就是系統(tǒng)在運(yùn)行的時(shí)候的一些機(jī)制,其中最主要的是消息機(jī)制。對(duì)于C語(yǔ)言,函數(shù)的調(diào)用在編譯的時(shí)候會(huì)決定調(diào)用哪個(gè)函數(shù)( C語(yǔ)言的函數(shù)調(diào)用請(qǐng)看這里 )。編譯完成之后直接順序執(zhí)行,無(wú)任何二義性。OC的函數(shù)調(diào)用成為消息發(fā)送。屬于動(dòng)態(tài)調(diào)用過(guò)程。在編譯的時(shí)候并不能決定真正調(diào)用哪個(gè)函數(shù)(事實(shí)證明,在編譯階段,OC可以調(diào)用任何函數(shù),即使這個(gè)函數(shù)并未實(shí)現(xiàn),只要申明過(guò)就不會(huì)報(bào)錯(cuò)。而C語(yǔ)言在編譯階段就會(huì)報(bào)錯(cuò))。只有在真正運(yùn)行的時(shí)候才會(huì)根據(jù)函數(shù)的名稱找到對(duì)應(yīng)的函數(shù)來(lái)調(diào)用。

       那OC是怎么實(shí)現(xiàn)動(dòng)態(tài)調(diào)用的呢?下面我們來(lái)看看OC通過(guò)發(fā)送消息來(lái)達(dá)到動(dòng)態(tài)調(diào)用的秘密。假如在OC中寫了這樣的一個(gè)代碼:

[objc] view plain?

<span style="font-size:18px;">[obj makeText];</span>  

       其中obj是一個(gè)對(duì)象,makeText是一個(gè)函數(shù)名稱。對(duì)于這樣一個(gè)簡(jiǎn)單的調(diào)用。在編譯時(shí)RunTime會(huì)將上述代碼轉(zhuǎn)化成

[objc] view plain?

objc_msgSend(obj,@selector(makeText));  

       首先我們來(lái)看看obj這個(gè)對(duì)象,iOS中的obj都繼承于NSObject。

[objc] view plain?

@interface NSObject <nsobject> {  

    Class isa  OBJC_ISA_AVAILABILITY;  

}</nsobject>  

       在NSObjcet中存在一個(gè)Class的isa指針。然后我們看看Class:

[objc] view plain?

typedef struct objc_class *Class;  

struct objc_class {  

  Class isa; // 指向metaclass  

     

  Class super_class ; // 指向其父類  

  const charchar *name ; // 類名  

  long version ; // 類的版本信息,初始化默認(rèn)為0,可以通過(guò)runtime函數(shù)class_setVersion和class_getVersion進(jìn)行修改、讀取  

  long info; // 一些標(biāo)識(shí)信息,如CLS_CLASS (0x1L) 表示該類為普通 class ,其中包含對(duì)象方法和成員變量;CLS_META (0x2L) 表示該類為 metaclass,其中包含類方法;  

  long instance_size ; // 該類的實(shí)例變量大小(包括從父類繼承下來(lái)的實(shí)例變量);  

  struct objc_ivar_list *ivars; // 用于存儲(chǔ)每個(gè)成員變量的地址  

  struct objc_method_list **methodLists ; // 與 info 的一些標(biāo)志位有關(guān),如CLS_CLASS (0x1L),則存儲(chǔ)對(duì)象方法,如CLS_META (0x2L),則存儲(chǔ)類方法;  

  struct objc_cache *cache; // 指向最近使用的方法的指針,用于提升效率;  

  struct objc_PRotocol_list *protocols; // 存儲(chǔ)該類遵守的協(xié)議  

}  

我們可以看到,對(duì)于一個(gè)Class類中,存在很多東西,下面我來(lái)一一解釋一下:

Class isa:指向metaclass,也就是靜態(tài)的Class。一般一個(gè)Obj對(duì)象中的isa會(huì)指向普通的Class,這個(gè)Class中存儲(chǔ)普通成員變量和對(duì)象方法(“-”開(kāi)頭的方法),普通Class中的isa指針指向靜態(tài)Class,靜態(tài)Class中存儲(chǔ)static類型成員變量和類方法(“+”開(kāi)頭的方法)。

Class super_class:指向父類,如果這個(gè)類是根類,則為NULL。

下面一張圖片很好的描述了類和對(duì)象的繼承關(guān)系:

注意:所有metaclass中isa指針都指向跟metaclass。而跟metaclass則指向自身。Root metaclass是通過(guò)繼承Root class產(chǎn)生的。與root class結(jié)構(gòu)體成員一致,也就是前面提到的結(jié)構(gòu)。不同的是Root metaclass的isa指針指向自身。

Class類中其他的成員這里就先不做過(guò)多解釋了,下面我們來(lái)看看:

@selector (makeText):

       這是一個(gè)SEL方法選擇器。SEL其主要作用是快速的通過(guò)方法名字(makeText)查找到對(duì)應(yīng)方法的函數(shù)指針,然后調(diào)用其函數(shù)。SEL其本身是一個(gè)Int類型的一個(gè)地址,地址中存放著方法的名字。對(duì)于一個(gè)類中。每一個(gè)方法對(duì)應(yīng)著一個(gè)SEL。所以iOS類中不能存在2個(gè)名稱相同的方法,即使參數(shù)類型不同,因?yàn)镾EL是根據(jù)方法名字生成的,相同的方法名稱只能對(duì)應(yīng)一個(gè)SEL。

下面我們就來(lái)看看具體消息發(fā)送之后是怎么來(lái)動(dòng)態(tài)查找對(duì)應(yīng)的方法的。

        首先,編譯器將代碼[obj makeText];轉(zhuǎn)化為objc_msgSend(obj, @selector (makeText));,在objc_msgSend函數(shù)中。首先通過(guò)obj的isa指針找到obj對(duì)應(yīng)的class。在Class中先去cache中通過(guò)SEL查找對(duì)應(yīng)函數(shù)method(猜測(cè)cache中method列表是以SEL為key通過(guò)hash表來(lái)存儲(chǔ)的,這樣能提高函數(shù)查找速度),若cache中未找到。再去methodList中查找,若methodlist中未找到,則取superClass中查找。若能找到,則將method加入到cache中,以方便下次查找,并通過(guò)method中的函數(shù)指針跳轉(zhuǎn)到對(duì)應(yīng)的函數(shù)中去執(zhí)行。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 龙州县| 句容市| 莱州市| 双桥区| 威信县| 台江县| 皮山县| 若羌县| 基隆市| 革吉县| 桓台县| 台东市| 广东省| 台东市| 张北县| 原阳县| 个旧市| 花莲县| 若尔盖县| 磐石市| 诸城市| 惠来县| 丹江口市| 文昌市| 海门市| 霍林郭勒市| 黎平县| 绥宁县| 商河县| 冀州市| 大城县| 株洲市| 康保县| 南安市| 贺兰县| 从化市| 屏南县| 隆昌县| 治县。| 山东省| 普洱|