为什么无法识别的选择器发送到实例?

时间:2019-03-28 14:55:33

标签: ios swift iphone xcode swift4.2

我正在尝试将一个便捷的Binding键盘绑定到uiview函数。我无法克服这个错误

  

***由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'-[Twitter.LoginVC handleKeyboard:]:无法识别的选择器已发送到实例0x7ffbf142e970'

class KeyboardService {

var constraint: NSLayoutConstraint!
var vc: UIViewController!

func bind(bottomConstraint: NSLayoutConstraint, vc: UIViewController) {
    constraint = bottomConstraint
    self.vc = vc
    NotificationService.instance.addKeyboardObservers(onVC: vc, handleKeyboardSelector: #selector(self.handleKeyboard(_:))) // **CRASHES HERE**
}

@objc func handleKeyboard(_ notification: NSNotification) {
    NotificationService.instance.handleKeyboard(notification: notification, bottomConstraint: constraint, vc: vc)
} 
}

这是我的notificationService:

class NotificationService {
static let instance  = NotificationService()

func addKeyboardObservers(onVC vc: UIViewController, handleKeyboardSelector: Selector) {
    NotificationCenter.default.addObserver(vc, selector: handleKeyboardSelector, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(vc, selector: handleKeyboardSelector, name: UIResponder.keyboardWillHideNotification, object: nil)
}
}

编辑:

class KeyboardService {

var constraint: NSLayoutConstraint!
var vc: UIViewController!

func bind(bottomConstraint: NSLayoutConstraint, vc: UIViewController) {
    constraint = bottomConstraint
    self.vc = vc
    NotificationService.instance.addKeyboardObservers(self, handleKeyboardSelector: #selector(self.handleKeyboard(_:)))
}

@objc func handleKeyboard(_ notification: NSNotification) {
    NotificationService.instance.handleKeyboard(notification: notification, bottomConstraint: constraint, vc: vc)
}

}

编辑2:

class KeyboardService {

var constraint: NSLayoutConstraint!
var vc: UIViewController!

func bind(bottomConstraint: NSLayoutConstraint, vc: UIViewController) {
    constraint = bottomConstraint
    self.vc = vc
    NotificationService.instance.addKeyboardObservers(self, handleKeyboardSelector: #selector(handleKeyboard(_:)))
}

@objc func handleKeyboard(_ notification: NSNotification) {
    NotificationService.instance.handleKeyboard(notification: notification, bottomConstraint: constraint, vc: vc)
}
}

在vc的viewDidLoad()中:

KeyboardService().bind(bottomConstraint: loginBtnBackViewBottomConstraint, vc: self)

1 个答案:

答案 0 :(得分:0)

您正在尝试将选择器发送到vc;但这是一个UIViewController,实际上没有称为handleKeyboard(_:)的方法。您应该将其更改为您的注册方法:

func addKeyboardObservers(_ observer: Any, handleKeyboardSelector: Selector) {
    NotificationCenter.default.addObserver(observer, selector: handleKeyboardSelector, name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(observer, selector: handleKeyboardSelector, name: UIResponder.keyboardWillHideNotification, object: nil)
}

然后,当您使用它时,您会这样做:

NotificationService.instance.addKeyboardObservers(self, handleKeyboardSelector: #selector(self.handleKeyboard(_:)))

如您所见,您现在要告诉您在self上触发选择器,因为实际上是self拥有该方法。 通常的规则是:将选择器发送到一个实例,因此必须具有所选方法的是该实例。


如果您确实希望将选择器发送到viewController实例,则可以创建一个extension并将该方法添加到每个UIViewController

extension UIViewController {

    @objc func handleKeyboard(_ notification: NSNotification) {
        // do your stuff here
    }
}

然后,在注册时执行:

NotificationService.instance.addKeyboardObservers(onVC: vc, handleKeyboardSelector: #selector(vc.handleKeyboard(_:))) // notice the vc.handleKeyboard instead of self.handleKeyboard

编辑 尝试将键盘服务保留在视图控制器中:

let keyboardService = KeyboardService()

override func viewDidLoad() {
    super.viewDidLoad()
    keyboardService.bind(bottomConstraint: loginBtnBackViewBottomConstraint, vc: self)
}