Создание протокола просмотра прокрутки в Swift 2.2
В настоящее время я разрабатываю приложение для iOS с формами входа и регистрации. Чтобы убедиться, что клавиатура не закрывает UITextField
s Я реализовал следующее решение, предоставленное Apple, и обсуждал в этом выпуске.
Чтобы кратко подвести итог, это решение использует UIScrollView
в котором размещены различные элементы пользовательского интерфейса и UIKeyboardDidShowNotification
а также UIKeyboardDidHideNotification
перемещать элементы вверх и вниз, когда клавиатура появляется / исчезает, так что UITextField
с не спрятаны.
Это работает как шарм, за исключением одного: для всех моих UIViewController
Я должен повторить тот же код. Чтобы решить мою проблему, я попытался:
- создать базу
UIViewController
предоставляя реализацию для различных функций, которые могут быть подклассами другимиUIViewController
s; - использовать протокол и расширение протокола, чтобы обеспечить реализацию по умолчанию для различных функций и сделать мой
UIViewController
соответствуют этому.
Оба решения не решили мою проблему. Для первого решения я не смог подключить UIScrollView
моего базового класса через Interface Builder, хотя он был объявлен.
@IBOutlet weak var scrollView: UIScrollView!
При попытке реализовать второе решение, UIViewController
Реализация моего протокола как-то не распознала заявленные методы и их реализации.
Декларация протокола:
protocol ScrollViewProtocol {
var scrollView: UIScrollView! { get set }
var activeTextField: UITextField? { get set }
func addTapGestureRecognizer()
func singleTapGestureCaptured()
func registerForKeyboardNotifications()
func deregisterForKeyboardNotifications()
func keyboardWasShown(notification: NSNotification)
func keyboardWillBeHidden(notification: NSNotification)
func setActiveTextField(textField: UITextField)
func unsetActiveTextField()
}
Расширение протокола реализует все функции, ожидаемые для addTapGestureRecognizer()
как я хотел бы избежать использования @objc
:
extension ScrollViewProtocol where Self: UIViewController {
// The implementation for the different functions
// as described in the provided links expect for the following method
func registerFromKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil, usingBlock: { notification in
self.keyboardWasShown(notification)
})
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidHideNotification, object: nil, queue: nil, usingBlock: { notification in
self.keyboardWillBeHidden(notification)
})
}
}
У кого-нибудь есть хорошее решение моей проблемы, зная, как можно избежать повторения кода, связанного с перемещением UITextField
s вверх и вниз, когда клавиатура появляется / исчезает? Или кто-нибудь знает, почему мои решения не сработали?
1 ответ
Я нашел решение. Я опубликую это на случай, если кто-то однажды сделает то же самое.
Итак, я закончила удаление UIScrollView
выход в моем базовом классе и заменяя его простым свойством, которое я установил в своих наследующих классах. Код для моего базового класса выглядит следующим образом:
import UIKit
class ScrollViewController: UIViewController, UITextFieldDelegate {
// MARK: Properties
var scrollView: UIScrollView!
var activeTextField: UITextField?
// MARK: View cycle
override func viewDidLoad() {
super.viewDidLoad()
let singleTap = UITapGestureRecognizer(target: self, action: #selector(singleTapGestureCaptured))
scrollView.addGestureRecognizer(singleTap)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
registerForKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
deregisterFromKeyboardNotifications()
}
// MARK: Gesture recognizer
func singleTapGestureCaptured(sender: AnyObject) {
view.endEditing(true)
}
// MARK: Keyboard management
func registerForKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardWillHideNotification, object: nil)
}
func deregisterFromKeyboardNotifications() {
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWasShown(notification: NSNotification) {
scrollView.scrollEnabled = true
let info : NSDictionary = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
var aRect : CGRect = self.view.frame
aRect.size.height -= keyboardSize!.height
if let activeFieldPresent = activeTextField {
if (!CGRectContainsPoint(aRect, activeFieldPresent.frame.origin)) {
scrollView.scrollRectToVisible(activeFieldPresent.frame, animated: true)
}
}
}
func keyboardWillBeHidden(notification: NSNotification) {
let info : NSDictionary = notification.userInfo!
let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().size
let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, -keyboardSize!.height, 0.0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
view.endEditing(true)
scrollView.scrollEnabled = false
}
// MARK: Text field management
func textFieldDidBeginEditing(textField: UITextField) {
activeTextField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
activeTextField = nil
}
}
А вот и наследующий код класса:
class ViewController: ScrollViewController {
@IBOutlet weak var scrollViewOutlet: UIScrollView! {
didSet {
self.scrollView = self.scrollViewOutlet
}
}
// Your view controller functions
}
Я надеюсь, это поможет!