成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

iOS開發(fā):詳解Objective-C runtime

移動(dòng)開發(fā) iOS
本文是我在 Alt Tech Talks: London 上關(guān)于 Objective-C runtime的演講總結(jié),如果你對(duì)Objective-C runtime感興趣的話,應(yīng)該看看這篇文章,特別是文章中的鏈接,一定會(huì)受益匪淺。

本文是我在 Alt Tech Talks: London 上關(guān)于 Objective-C runtime的演講總結(jié),如果你對(duì)Objective-C runtime感興趣的話,應(yīng)該看看這篇文章,特別是文章中的鏈接,一定會(huì)受益匪淺。 

什么是Objective-C runtime?

簡(jiǎn)單來說,Objective-C runtime是一個(gè)實(shí)現(xiàn)Objective-C語言的C庫。對(duì)象可以用C語言中的結(jié)構(gòu)體表示,而方法(methods)可以用C函數(shù)實(shí)現(xiàn)。事實(shí)上,他們 差不多也是這么干了,另外再加上了一些額外的特性。這些結(jié)構(gòu)體和函數(shù)被runtime函數(shù)封裝后,Objective-C程序員可以在程序運(yùn)行時(shí)創(chuàng)建,檢 查,修改類,對(duì)象和它們的方法。

除了封裝,Objective-C runtime庫也負(fù)責(zé)找出方法的最終執(zhí)行代碼。當(dāng)程序執(zhí)行[object doSomething]時(shí),不會(huì)直接找到方法并調(diào)用。相反,一條消息(message)會(huì)發(fā)送給對(duì)象(在這兒,我們通常叫它接收者)。runtime庫 給次機(jī)會(huì)讓對(duì)象根據(jù)消息決定該作出什么樣的反應(yīng)。Alan Kay反復(fù)強(qiáng)調(diào)消息傳遞(message-passing)是Smalltalk最重要的部分(Objective-C根據(jù)Smalltalk發(fā)展而來),而不是對(duì)象: 

由于以前關(guān)于這個(gè)話題我創(chuàng)造了“對(duì)象”這個(gè)詞,現(xiàn)在很多人都對(duì)這個(gè)概念趨之若鶩,這讓我感到非常遺憾。

其實(shí)這里面更為重要的理念是“消息命令”(messaging),這才是Smalltalk的核心內(nèi)容(現(xiàn)在尚有一些內(nèi)容還沒有全部完成)。日 語中有個(gè)簡(jiǎn)短的單詞叫做“ma”,它用來表示兩個(gè)物體之間的東西,在英語中和它最相近的單詞也許是“interstitial”。制造一個(gè)龐大且可擴(kuò)展系 統(tǒng)的關(guān)鍵是設(shè)計(jì)它各個(gè)模塊之間的通信方式,而不是關(guān)注它的內(nèi)部屬性和行為。 

實(shí)際上,在一篇介紹Smalltalk虛擬機(jī)的文章里,這門編程技術(shù)被叫做消息傳遞或者消息傳送范式。“面向?qū)ο?rdquo;通常用來描述內(nèi)存管理系統(tǒng)。

在演講和文章中都使用ObjC runtime這個(gè)詞,看似只有一個(gè),實(shí)際上存在很多runtime庫。雖然它們都支持對(duì)象的自省檢查和消息接收,但是它們卻有不同的特性和實(shí)現(xiàn)方式(例 如,同樣是發(fā)送消息,Apple的runtime用一步完成,而GNU runtime會(huì)先查詢這些消息,然后執(zhí)行查找到的函數(shù)分兩步完成)。以下所有的討論,都是基于Apple的***runtime庫(蘋果公司在OSX 10.5和iOS發(fā)布時(shí)的版本)。 

在那次演講中,我決定研究runtime庫某些領(lǐng)域的功能。我找了一些希望更透徹了解的東西,然后把它們做成問答的形式組成我的演講。

動(dòng)態(tài)創(chuàng)建類

如何實(shí)現(xiàn)Key-Value Observing?

 當(dāng)我在準(zhǔn)備這次演講時(shí),一篇叫做KVO considered harmful 的文章開始擁有很多擁躉。它提出了很多對(duì)KVO正確的批評(píng),但相對(duì)于舍棄觀察者模式不用,我更想探索出一種新的實(shí)現(xiàn)方式。 

KVO實(shí)現(xiàn)觀察者模式的關(guān)鍵是它偷偷摸摸將被觀察對(duì)象的類改變了,它子類化原來的類后,就能夠自定義該對(duì)象的方法來調(diào)用KVO的回調(diào)方法。這些都是通過 objc_duplicateClass這個(gè)方法完成,但很遺憾,這個(gè)方法并不公開,我們無法私自調(diào)用。 

條條大路通羅馬,好在除了objc_duplicateClass,還有其他方法可以通過使用秘密子類化的方式實(shí)現(xiàn)觀察者模式,比如創(chuàng)建和注冊(cè) “class pair”。那么什么是class pair呢?對(duì)于Objective-C的類來說,都有一對(duì)Class的對(duì)象來定義它:Class對(duì)象定義了這個(gè)類的實(shí)例方法,而metaclass定義 了這個(gè)類的類方法。所以每個(gè)class其實(shí)是它metaclass的單例。 

這個(gè)代碼展 示了觀察者模式的工作原理。當(dāng)你給對(duì)象增加觀察者時(shí),這個(gè)對(duì)象首先會(huì)檢查自己是否可被觀察,如果是,它會(huì)新創(chuàng)建一個(gè)類,用我們自己的-dealloc替代 原來類的方法,同樣它也會(huì)把-class方法替換掉,類似于KVO被觀察對(duì)象,當(dāng)你訪問被觀察對(duì)象的類名時(shí),返回的是它原來的類名,而不是新生成的類。

創(chuàng)建完類后,我們需要照著 Key-Value Coding為屬性增加一個(gè)setter方法:這個(gè)setter方法會(huì)獲取這個(gè)屬性修改前的值和修改后的值,然后調(diào)用block形式的回調(diào)函數(shù),將這兩個(gè)值告訴觀察者。代碼中根據(jù)我們的意愿,這個(gè)block可以異步調(diào)用。 

請(qǐng)注意, -addObserverForKey:withBlock:會(huì)使用s object_setClass() 將被觀察對(duì)象的類替代為新組建的類。這樣做最主要的目的是將消息轉(zhuǎn)變?yōu)榉椒ǖ姆绞礁淖儯沁@需要非常小心,原來的類和新的類必須有相同的成員變量布局。 因?yàn)槌蓡T變量也是用過runtime訪問,修改某個(gè)對(duì)象的類可能導(dǎo)致runtime無法找到對(duì)應(yīng)的變量。 

我們?cè)诖鎯?chǔ)觀察者集合時(shí)遇到些麻煩,因?yàn)闆]地方去存它們。給ObserverPattern這個(gè)類增加成員變量不起作用,因?yàn)楦緵]有生成這個(gè)類的對(duì)象。被觀察對(duì)象的成員變量是它原來類的,它并沒有考慮過這些觀察者。 

Objective-C runtime通過引入 associated objects 幫助我們擺脫這個(gè)困境。在runtime里,理論上所有對(duì)象都可以擁有包含其他對(duì)象的字典。通過associated references,被觀察對(duì)象可以存儲(chǔ)和訪問他們的觀察者,而不需要額外的成員變量。

如果你運(yùn)行多次后,你會(huì)發(fā)現(xiàn)ObserverPattern 還是有點(diǎn)小毛病的。由于觀察者回調(diào)是異步調(diào)用的,觀察者接

收到的變化事件也是亂序的。這意味著觀察者其實(shí)無法區(qū)分被觀察屬性的最終狀態(tài)是什么,回調(diào)中的新值可能早已被修改。我這樣做的目的是為了說明在KVO中同步調(diào)用回調(diào)其實(shí)是個(gè)有用的特色,并非bug。 

創(chuàng)建對(duì)象

那些額外的字節(jié)都是干啥用的?

當(dāng)你創(chuàng)建一個(gè) Objective-C對(duì)象時(shí),runtime會(huì)在實(shí)例變量存儲(chǔ)區(qū)域后面再分配一點(diǎn)額外的空間。這么做的目的是什么呢?你可以獲取這塊空間起始指針(用 object_getIndexedIvars),然后就可以索引實(shí)例變量(ivars)。好吧,下面我會(huì)使用自定義數(shù)組來說明一下索引ivars的用 處。 

讓我們創(chuàng)建一個(gè)數(shù)組!從這個(gè)SimpleArray中可以看到兩件事情:最明顯的一件是它使用了類簇模式。 當(dāng)使用+alloc方法返回對(duì)象時(shí),一般情況下已經(jīng)為這個(gè)對(duì)象分配了所有的內(nèi)存,但是在這個(gè)例子中,在+alloc時(shí)并不知道需要多大的內(nèi)存空間。只有當(dāng) 調(diào)用了 -initWithObjects:count:以后,才能根據(jù)數(shù)組內(nèi)對(duì)象數(shù)量計(jì)算出這個(gè)數(shù)組需要多大的內(nèi)存,所以+alloc只是返回一個(gè)占位符,只有 在初始化后才會(huì)分配和返回真正的數(shù)組對(duì)象。 

或許你會(huì)問為什么我們要用類簇把事情搞那么復(fù)雜,使用 calloc()另外分配一塊大小合適的緩存,然后把那些對(duì)象指針存到里面不就得了?答案是希望利用局部性原理提高訪問性能。從數(shù)組的設(shè)計(jì)上我們可以看出,每次數(shù)組指針被訪問時(shí),之后會(huì)有很大幾率訪問到緩存指針,所以把它們肩并肩的放入內(nèi)存意味著找到其中一個(gè)就是找到了另外一個(gè)。 

消息派發(fā)

消息如何轉(zhuǎn)發(fā)?

Objective-C其中一個(gè)強(qiáng)大特性是對(duì)象不需要實(shí)現(xiàn)某個(gè)方法,盡管它在編譯時(shí)聲明了該選擇符(selector)。但它可以在運(yùn)行時(shí)再?zèng)Q 定方法實(shí)現(xiàn),或者將這些消息轉(zhuǎn)發(fā)給其他對(duì)象,或者發(fā)出異常,亦或做一些其他事情。但是這個(gè)特性的某些方面曾經(jīng)一直困擾我:消息轉(zhuǎn)發(fā)(message forwarding)會(huì)調(diào)用 -forwardInvocation:,然后傳入一個(gè)NSInvocation 對(duì)象。但是這個(gè)NSInvocation 類是在Foundation庫中定義的,難道說runtime工作需要Foundation配合? 

我試著挖掘其中的原因,發(fā)現(xiàn)答案并不是我想的那樣,runtime不需要知道Foundation。runtime會(huì)讓程序定義轉(zhuǎn)發(fā)函數(shù) (forwarding function),當(dāng) objc_msgSend()無法找到該selector的實(shí)現(xiàn)時(shí),那個(gè)轉(zhuǎn)發(fā)函數(shù)就會(huì)被調(diào)用。程序一啟動(dòng),CoreFoundation就將 -forwardInvocation:定義成轉(zhuǎn)發(fā)函數(shù)。 

讓我們來創(chuàng)建一個(gè)Ruby! 當(dāng)然并不是真的實(shí)現(xiàn)完整的Ruby,Ruby有一個(gè)叫做#method_missing的函數(shù),當(dāng)對(duì)象收到一個(gè)它沒有實(shí)現(xiàn)的消息時(shí),這個(gè)函數(shù)就會(huì)被調(diào)到, 這和Smalltalk的做法比較相似。使用objc_setForwardHandler,我們也能在Objective-C的類中實(shí)現(xiàn)類似Ruby的 methodMissing:方法。 

總結(jié)

Objective-C runtime可以有效的幫助我們?yōu)槌绦蛟黾雍芏鄤?dòng)態(tài)的行為。一些開發(fā)者除了使用method swizzling幫助調(diào)試程序,并不會(huì)在實(shí)際程序中使用它,但runtime編程的確有很多功能,它應(yīng)該成為實(shí)際應(yīng)用代碼編寫的重要工具。

原文地址:http://blog.securemacprogramming.com/2013/12/by-your-_cmd/

責(zé)任編輯:閆佳明 來源: oschina
相關(guān)推薦

2011-04-08 10:51:17

Objective-CiOS

2011-07-29 16:16:30

Objective-c block

2011-08-17 10:58:59

Objective-C構(gòu)造函數(shù)

2011-07-29 15:47:21

iPhone開發(fā) Objective- C

2015-09-07 09:53:02

Objective-CRuntime

2015-07-08 10:51:27

Objective-CRuntime

2014-09-26 09:49:48

SwiftObjective-C

2011-07-28 15:11:23

iOS Objective-

2012-04-23 11:00:56

iOS開發(fā)Objective-CJavaScript

2015-10-08 10:01:10

Objective-CLayout

2011-07-18 16:36:51

Objective-C XCode

2011-08-17 10:29:39

Objective-C預(yù)處理

2011-08-04 09:47:33

iOS Objective- JavaScript

2011-08-04 13:38:01

Objective-C C++

2011-07-27 16:55:12

Objective-c 閉包

2011-08-01 17:11:43

Objective-C 函數(shù)

2011-08-15 14:32:42

Objective-C委托協(xié)議

2014-04-28 09:56:56

Objective-CiOS命名空間

2011-08-17 11:05:22

Objective-C方法

2011-07-08 18:44:09

Objective-C Self Super
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧洲亚洲一区二区三区 | 一区欧美| 激情综合五月 | 日韩在线中文 | 日韩视频在线观看一区二区 | 亚洲精品性视频 | 国产精品99久久久久久动医院 | 欧美日一区 | 男女羞羞视频免费 | 夜夜骑首页 | 91在线视频观看免费 | 在线观看www高清视频 | 久久久精彩视频 | www.天天操 | 伊人久久伊人 | 丁香综合| 欧美精品一区二区三 | 欧美日韩高清免费 | 国产精品久久久99 | 色久五月| 99视频在线看 | 欧美一区二区三区在线观看视频 | 深夜福利影院 | 天天操天天天干 | 亚洲三级在线 | 国产在线网站 | 麻豆亚洲| 欧美成人激情 | 91正在播放 | 国产精品欧美一区喷水 | 最新中文字幕在线 | 婷婷综合激情 | 亚洲综合在线网 | av天天看 | 国产欧美精品一区二区色综合朱莉 | 欧美一区二区激情三区 | a级性视频 | 日韩精品一区二区久久 | 国产 欧美 日韩 一区 | 中文字幕 欧美 日韩 | 中文av在线播放 |