-1

我目前正在开发一个带有登录和注册表单的 iOS 应用程序。为了确保键盘不覆盖任何UITextFields,我实施了Apple提供的以下解决方案,并在本期中进行了讨论。

简单总结一下,此解决方案使用 a UIScrollView,其中放置了不同的 UI 元素,UIKeyboardDidShowNotificationUIKeyboardDidHideNotification在键盘出现/消失时上下移动元素,以便UITextField不隐藏 s。

除了一件事之外,这就像一个魅力:对于我所有的UIViewControllers,我必须重复相同的代码。为了解决我的问题,我尝试过:

  • 创建一个 base UIViewController,为不同的功能提供实现,可以是其他UIViewController的子类;
  • 使用协议和协议扩展为不同的功能提供默认实现,并使 my UIViewControllers 符合它。

两种解决方案都没有解决我的问题。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 相关的代码?或者有谁知道为什么我的解决方案不起作用?

4

1 回答 1

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

}

我希望这个能帮上忙!

于 2016-04-14T08:34:30.810 回答