Pages

Tuesday, December 21, 2010

Selector in Objective-C


Xcode
在物件導向程式語言,呼叫 methods 是一種由記憶體呈現控制實體端點指到程式碼,這樣對於設計程式會有限制,所以後來有 "command handling" 這種的需要,這被組織收錄在 Chain of Responsibility design pattern 中。

Chain of Responsibility 裡面的定義:"Avoid coupling the sender of a request to it's receiver by giving more than one object a chance to handle the request Chain the receiving objects and pass the request along the chain until an object handles it."規劃動機是希望可以分離 senders 和 receivers,透過多個 objects 來處理這些 request,request 就一直傳遞直到有真的實作的部份。


而 Cocoa 使用了以上這種方式,使得 Objective-C 的 late binding 開啓了更多的彈性。 在 Objective-C,methods 可以用 selector 來當代表呈現,一個字串來形容描述 method 要被呼叫的。當 message 傳遞,selector 會在 run time 時候傳遞出去。對應到符合的 method,然後進入該實作的 method 裡面繼續執行。

"selector" 有兩種含意。一種是可以當使用到程式碼對照 (source-code message),來參考對應 method 名稱。二種是可以是當編譯過後,參考到獨特定義名稱。編譯後的 selectors (Compiled selectors) 是使用型態 SEL。所有同樣名稱擁有同樣的 selector。可以使用 selector 來觸發啓用該物件的 method,這在 target-action design pattern 有用到。

編譯器會把每一個 method 名稱寫到 table,那個名稱就會成為獨立的辨識值 (identifier) 呈現在 runtime 時候。Runtime system 會確定每一個 identifier 是獨立的,沒有兩個 selectors 會是一樣,所有 methods 擁有同樣名稱,會擁有同樣的 selector。


以此為例,定義一個 SEL,讓它分配成為一個 method。而且實際實作的 method 是在 Runtime 才去察看,不是在編譯階段。這邊可能會有點 performance 探討,但是使用這種 late binding 可以讓同樣 selector 去對應到不同的實作。


在 Target-Action design pattern 裡面,我們平常都是會在 xxx.h 裡面去宣告我們的 method 定義成為 IBAction,再到 Interface Builder 裡面拖拉元件,配製事件連到某某 IBAction,這邊也是透過 selector 方式來指定 method 的。

在配製 selector 裡面的名稱時,要注意 method 名稱。例如配製一個 NSString 裡面的 lowercaseString,就要寫 "lowercaseString",而不是 "lowercaseString:" (多了 ":" 符號)。因為這邊要看該 method 是否需要傳遞參數,而對照到 API,lowercaseString 是不用傳遞參數的。那什麼時候要加入呢?當需要傳遞超過一個以上參數時候,要給與 ":" 符號,例如 "compare:", "options:", "setSize:" 等等。


另外想了解更多可以額外參考 wikipeida 上 Cocoa (API) 的 Late binding 以及 developer.app.com/library 的 selectors 文件。

1 comment: