我目前正在使用登录和注册表单开发iOS应用程序。为了确保键盘不会覆盖任何UITextField
,我实施了Apple提供的以下解决方案,并在此issue中进行了讨论。
简单总结一下,此解决方案使用UIScrollView
放置不同的UI元素,UIKeyboardDidShowNotification
和UIKeyboardDidHideNotification
在键盘出现时上下移动元素/消失,以便UITextField
不被隐藏。
除了一件事之外,这就像魅力一样:对于我所有的UIViewController
,我必须重复相同的代码。为了解决我的问题,我尝试过:
UIViewController
,为不同的函数提供实现,可以是其他UIViewController
的子类; UIViewController
符合它。这两种解决方案都没有解决我的问题。对于第一个解决方案,虽然已经声明,但我无法通过Interface Builder连接我的基类的UIScrollView
。
@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相关的代码?或者有谁知道为什么我的解决方案不起作用?
答案 0 :(得分:0)
我找到了解决方案。我会发布它以防万一有人做同样的事情。
所以,我最终删除了我的基类中的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
}
我希望这会有所帮助!