原創(chuàng)文章阻问,歡迎轉(zhuǎn)載锉屈。轉(zhuǎn)載請(qǐng)注明:關(guān)東升的博客
實(shí)現(xiàn)目標(biāo)與動(dòng)作關(guān)聯(lián)使用UIControl類(lèi)addTarget(_:action:forControlEvents:)方法挑童,示例代碼如下:
button.addTarget(self, action: "onClick:",
?forControlEvents: UIControlEvents.TouchUpInside)
其中的action參數(shù)"onClick:"事實(shí)上就是選擇器(Selector)蚣录。
問(wèn)題提出
任何能夠?qū)⒎椒ㄕ{(diào)用的綁定推遲到運(yùn)行期逗旁,在編譯時(shí)方法調(diào)用者不需要知道要調(diào)用的方法是什么淘捡,這個(gè)可以降低調(diào)用者與被調(diào)用者之間的耦合度藕各,這樣就語(yǔ)言就很靈活。在C語(yǔ)言在提供一種函數(shù)指針技術(shù)焦除,Objective-C和Swift語(yǔ)言都提供選擇器(Selector)類(lèi)型激况,它是C語(yǔ)言函數(shù)指針的面向?qū)ο筇娲夹g(shù)。
選擇器在Cocoa和Cocoa Touch中的目標(biāo)動(dòng)作膘魄、通知和委托等模式中方法的調(diào)用實(shí)現(xiàn)的關(guān)鍵乌逐。
解決方案
Objective-C中選擇器是SEL數(shù)據(jù)類(lèi)型,使用@selector()語(yǔ)句調(diào)用创葡,調(diào)用onClick:方法的Objective-C示例代碼如下:
SEL selector = @selector(onClick:);
[button addTarget:self action: selector
? forControlEvents: UIControlEventTouchUpInside];
Swift中雖然沒(méi)有提供SEL數(shù)據(jù)類(lèi)型浙踢,而是提供了Selector結(jié)構(gòu)體,通過(guò)方法名字符串構(gòu)建Selector實(shí)例灿渴,示例代碼如下:
button.addTarget(self, action: Selector("onClick:"),
?forControlEvents: UIControlEvents.TouchUpInside)
通過(guò)選擇器調(diào)用方法洛波,關(guān)鍵是方法名字胰舆,它有一定規(guī)律的。窮其根本是源自于Objective-C多重參數(shù)方法命名規(guī)律蹬挤。方法名的冒號(hào)暗示了方法名應(yīng)該具有幾個(gè)參數(shù)缚窿,下面我們看幾個(gè)示例:
//選擇器為"onClick:"
func onClick(sender: AnyObject) {
NSLog("onClick:")
}
//選擇器為"onClick:forEvent:"
func onClick(sender: AnyObject, forEvent event: UIEvent) {
NSLog("onClick:forEvent:")
}
//選擇器為"onClickWithExtSender:forEvent:"
func onClick(extSender sender: AnyObject, forEvent event: UIEvent) {
NSLog("onClickWithExtSender:forEvent:")
}
出于數(shù)據(jù)封裝的需要,我們會(huì)在方法前面加private闻伶,使其變?yōu)樗接蟹椒ū豕ィa如下。
private func onClick(sender: AnyObject) {
NSLog("onClick:")
}
但是這樣方法在調(diào)用時(shí)候會(huì)出現(xiàn)如下錯(cuò)誤:
unrecognized selector sent to instance 0x7f7f81499b10'
這個(gè)錯(cuò)誤的意思是沒(méi)有找到選擇器所指定的方法蓝翰,也就是沒(méi)有找到onClick:方法光绕。正確的做法是在方法前面添加@objc屬性注釋?zhuān)@說(shuō)明選擇器是在objc runtime運(yùn)行環(huán)境下調(diào)用的。
//選擇器為"onClick:"
@objc private func onClick(sender: AnyObject) {
NSLog("onClick:")
}