原文在這里Swift 中 Selector 方法的訪問權(quán)限控制問題,感覺寫的很好,道理講的簡(jiǎn)潔而明了,記錄一下。
private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
// ....
}
不想將beginDragged:方法暴露出去,所以將其定義為一個(gè)private方法。方法的定義一切正常,手勢(shì)的Selector方法也設(shè)置正常,用#selector調(diào)用時(shí)卻報(bào)了未找到方法的異常。那問題可能就應(yīng)該在訪問權(quán)限問題上了。
我們知道Selector是Objective-C的產(chǎn)物,它用于在運(yùn)行時(shí)作為一個(gè)鍵值去找到對(duì)應(yīng)方法的實(shí)現(xiàn)。一個(gè)Objective-C的方法是由objc_method結(jié)束體定義的,其聲明如下:
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE; // 方法名
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE; // 方法實(shí)現(xiàn)
}
這就要求selector引用的方法必須對(duì)ObjC運(yùn)行時(shí)是可見的。而Swift是靜態(tài)語言,雖然繼承自NSObject的類默認(rèn)對(duì)ObjC運(yùn)行時(shí)是可見的,但如果方法是由private關(guān)鍵字修飾的,則方法默認(rèn)情況下對(duì)ObjC運(yùn)行時(shí)并不是可見的,所以就導(dǎo)致了以上的異常:運(yùn)行時(shí)并沒找到SwipeCardView類的beginDragged:方法。
所以,我們必須將private修飾的方法暴露給運(yùn)行時(shí)。正確的做法是在 private 前面加上 @objc 關(guān)鍵字,這樣就OK了。
@objc private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
// ....
}
另外需要注意的是,如果我們的類是純Swift類,而不是繼承自NSObject,則不管方法是private還是internal或public,如果要用在Selector中,都需要加上@objc修飾符。