今天用Swift寫了個視圖效床,在視圖上加個手勢茶敏,如下所示:
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "beginDragged:")
view1.addGestureRecognizer(panGestureRecognizer)
運(yùn)行了下程序,然后崩潰了织鲸。崩潰日志如下:
[**.SwipeCardView beginDragged:]: unrecognized selector sent to instance 0x125e5bc10
而我已經(jīng)在SwipeCardView類中定義了beginDragged:方法,如下所示:
private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
// ....
}
由于我并不想將beginDragged:方法暴露出去,所以將其定義為一個private方法砸烦。方法的定義一切正常,手勢的Selector方法也設(shè)置正常绞吁,卻報了未找到方法的異常幢痘。那問題可能就應(yīng)該在訪問權(quán)限問題上了。
我們知道Selector是Objective-C的產(chǎn)物家破,它用于在運(yùn)行時作為一個鍵值去找到對應(yīng)方法的實現(xiàn)颜说。一個Objective-C的方法是由objc_method結(jié)構(gòu)體定義的购岗,其聲明如下:
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE; // 方法名
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE; // 方法實現(xiàn)
}
這就要求selector引用的方法必須對ObjC運(yùn)行時是可見的。而Swift是靜態(tài)語言门粪,雖然繼承自NSObject的類默認(rèn)對ObjC運(yùn)行時是可見的喊积,但如果方法是由private關(guān)鍵字修飾的,則方法默認(rèn)情況下對ObjC運(yùn)行時并不是可見的玄妈,所以就導(dǎo)致了以上的異常:運(yùn)行時并沒找到SwipeCardView類的beginDragged:方法乾吻。
所以,我們必須將private修飾的方法暴露給運(yùn)行時措近。正確的做法是在 private 前面加上 @objc 關(guān)鍵字溶弟,這樣就OK了。
@objc private func beginDragged(gestureRecognizer: UIPanGestureRecognizer) {
// ....
}
另外需要注意的是瞭郑,如果我們的類是純Swift類辜御,而不是繼承自NSObject,則不管方法是private還是internal或public屈张,如果要用在Selector中擒权,都需要加上@objc修飾符。