有很多人,認為block的推廣可取代代理設計模式,其實block并不能取代代理,代理的模式可以讓代碼邏輯性更強,更整潔,也會有更高的可讀性和可擴充性。相比之下,我覺得block更多的是取代了選擇器@selector。
@selector是什麼?我們要首先明白sel,sel并不是一種對象類型,我們通過xcode的字型顔色就可以判斷出來,它是一個關鍵字,就像int,long一樣,它聲明了一種類型:類方法指針。其實就可以了解為一個函數指針。比如,我們生命一個叫mylog的函數指針:
<a href="http://my.oschina.net/u/2340880/blog/396367#">?</a>
1
2
3
4
5
6
7
<code>#import "viewcontroller.h"</code>
<code>@interface viewcontroller ()</code>
<code>{</code>
<code> </code><code>sel mylog;</code>
<code>}</code>
<code>@end</code>
聲明出了這個指針,我們該如何給它傳遞這個函數呢?有兩種方式:
1、在編譯時,使用@selector來取得函數
現在,我們應該明白@selector是什麼了,它是一個編譯标示,我們通過它來取到相應函數。
8
9
10
11
12
13
14
15
16
17
18
19
<code>@implementation viewcontroller</code>
<code>- (</code><code>void</code><code>)viewdidload {</code>
<code> </code><code>[super viewdidload];</code>
<code> </code><code>// do any additional setup after loading the view, typically from a nib.</code>
<code> </code><code>mylog = @selector(mylogl);</code>
<code> </code><code>//通過performselector來執行方法</code>
<code> </code><code>[self performselector:mylog];</code><code>//列印 “mylog”</code>
<code> </code>
<code>-(</code><code>void</code><code>)mylogl{</code>
<code> </code><code>nslog(@</code><code>"mylog"</code><code>);</code>
2、在運作時,通過nsselectorfromstring方法來取到相應函數:
20
21
22
<code> </code><code>mylog = nsselectorfromstring(@</code><code>"mylogn"</code><code>);</code>
<code> </code><code>[self performselector:mylog];</code>
<code>-(</code><code>void</code><code>)mylogn{</code>
這兩種方式的差别在于,編譯時的方法如果沒有找到相應函數,xcode會報錯,而運作時的方法不會。
至于sel的應用,我相信最廣泛的便是target——action設計模式了。我們來簡單模拟一下系統button的工作原理:
我們先建立一個繼承于uibutton的類:
.h檔案:
<code>#import <uikit/uikit.h></code>
<code>@interface mybutton : uibutton</code>
<code>-(</code><code>void</code><code>)addmytarget:(id)target action:(sel)action;</code>
.m檔案
<code>#import "mybutton.h"</code>
<code>@implementation mybutton</code>
<code> </code><code>sel _action;</code>
<code> </code><code>id _target;</code>
<code>-(</code><code>void</code><code>)addmytarget:(id)target action:(sel)action{</code>
<code> </code><code>_target=target;</code>
<code> </code><code>_action=action;</code>
<code>-(</code><code>void</code><code>)touchesbegan:(nsset *)touches withevent:(uievent *)event{</code>
<code> </code><code>[_target performselector:_action];</code>
在外部:
<code> </code><code>mybutton * btn = [[mybutton alloc]initwithframe:cgrectmake(100, 100, 60, 60)];</code>
<code> </code><code>btn.backgroundcolor=[uicolor redcolor];</code>
<code> </code><code>[btn addmytarget:self action:@selector(click)];</code>
<code> </code><code>[self.view addsubview:btn];</code>
<code>-(</code><code>void</code><code>)click{</code>
<code> </code><code>nslog(@</code><code>"點選了btn"</code><code>);</code>
當然,如果要調用參數,系統提供的預設參數不超過兩個,如果參數很多,一種是我們可以通過字典傳參,另一種方法比較複雜,在這裡先不讨論。