В моем проекте у меня есть несколько контроллеров представлений, которые являются подклассами UITableViewController, UIViewController, на каждом я хочу реализовать такое поведение:Использование расширения протокола, чтобы закрыть клавиатуру вне крана
Когда пользователь нажимает за пределами текста поле должно отклонить клавиатуру, которая была видна, когда пользователь входил в нее.
можно легко реализовать путем определения крана жест распознаватель и ассоциирования селектор, чтобы закрыть клавиатуру:
class MyViewController {
override func viewDidLoad() {
super.viewDidLoad()
configureToDismissKeyboard()
}
private func configureToDismissKeyboard() {
let tapGesture = UITapGestureRecognizer(target: self, action: "hideKeyboard")
tapGesture.cancelsTouchesInView = true
form.addGestureRecognizer(tapGesture)
}
func hideKeyboard() {
form.endEditing(true)
}
}
Поскольку я должен реализовать такое же поведение в нескольких контроллерах зрения, я пытаюсь определить способ избежать использования повторяющегося кода в нескольких классах.
Один из вариантов для меня - это определить BaseViewController
, который является подклассом UIViewController
, со всеми описанными выше методами, а затем подклассифицирует каждый из моих контроллеров представления на BaseViewController
. Проблема с этим подходом заключается в том, что мне нужно определить два BaseViewController
s один для UIViewController
и один для UITableViewController
, так как я использую подклассы обоих.
Другой вариант, который я пытаюсь использовать, - Protocol-Oriented Programming
. Поэтому я определил протокол:
protocol DismissKeyboardOnOutsideTap {
var backgroundView: UIView! { get }
func configureToDismissKeyboard()
func hideKeyboard()
}
Затем определяется его расширение:
extension DismissKeyboardOnOutsideTap {
func configureToDismissKeyboard() {
if let this = self as? AnyObject {
let tapGesture = UITapGestureRecognizer(target: this, action: "hideKeyboard")
tapGesture.cancelsTouchesInView = true
backgroundView.addGestureRecognizer(tapGesture)
}
}
func hideKeyboard() {
backgroundView.endEditing(true)
}
}
На мой взгляд контроллера я подтвердил протокол:
class MyViewController: UITableViewController, DismissKeyboardOnOutsideTap {
var backgroundView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// configuring background view to dismiss keyboard on outside tap
backgroundView = self.tableView
configureToDismissKeyboard()
}
}
Проблема есть - выше код разбивая с исключение:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyProject.MyViewController hideKeyboard]: unrecognized selector sent to instance 0x7f88c1e5d700'
Чтобы избежать этой аварии мне нужно переопределить hideKeyboard
функции в пределах MyViewController
класса, побеждающая свою цель избежать повторяющегося кода :(
Пожалуйста, предложить, если я делаю любую вещь неправильно здесь, и есть ли лучший способ реализовать мой требование.
Кажется, что из MyViewController вы хотите повторно использовать функцию hideKeyboard в вашем BaseViewControllers. Но вы не объявили, что ваш MyViewController является подклассом BaseViewControllers. –
Эй, спасибо за ваш ответ, но обратите внимание, что использование «BaseViewController» было первым вариантом, который я стараюсь избегать по причинам, указанным в моем опубликованном вопросе. В настоящее время я пытаюсь использовать «протокол-ориентированное программирование» вместо него :) – Devarshi
Если вы используете протокол-ориентированное программирование, вам нужно реализовать hideKeyboard в MyViewController и, следовательно, иметь повторяющийся код. Протокол помогает вам просто определить «протокол», который должен быть согласован. –