-1

Ich entwickle gerade eine iOS-Anwendung mit Anmelde- und Anmeldeformularen. Um sicherzustellen, dass die Tastatur keine UITextField s abdeckt, habe ich die folgende Lösung implementiert, die von Apple bereitgestellt und in dieser issue diskutiert wird.Erstellen eines Scroll-Ansichtsprotokolls in swift 2.2

kurz Um es zusammenzufassen, diese Lösung eine UIScrollView verwendet, in dem die verschiedenen Elemente der Benutzeroberfläche platziert und UIKeyboardDidShowNotification und UIKeyboardDidHideNotification, um die Elemente nach oben und nach unten, wenn die Tastatur erscheint/verschwindet, so dass die UITextField s nicht versteckt sind.

Dies funktioniert wie ein Charme mit Ausnahme einer Sache: Für alle meine UIViewController s muss ich den gleichen Code wiederholen. Zu meinem Problem angeht Ich habe versucht:

  • um eine Basis zu schaffen UIViewController, eine Implementierung für die verschiedenen Funktionen bereitstellt, kann das sein Subklassen von den anderen UIViewController s;
  • um ein Protokoll und eine Protokollerweiterung zu verwenden, um eine Standardimplementierung für die verschiedenen Funktionen bereitzustellen und meine UIViewController s konform zu machen.

Beide Lösungen lösten mein Problem nicht. Bei der ersten Lösung konnte ich den UIScrollView meiner Basisklasse über den Interface Builder nicht verbinden, obwohl er deklariert wurde.

@IBOutlet weak var scrollView: UIScrollView! 

Beim Versuch, die zweite Lösung zu implementieren, die UIViewController mein Protokoll implementiert irgendwie nicht die deklarierten Methoden und die Umsetzungen erkennen.

Die Protokollerklärung:

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() 
} 

Die Protokollerweiterung implementiert alle Funktionen für die addTapGestureRecognizer() erwarten, wie ich @objc mit vermeiden möchte:

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) 
     }) 
    } 
} 

Hat jemand eine gute Lösung für mein Problem , wissentlich wie könnte ich vermeiden, den Code zu wiederholen, der sich darauf bezieht, die UITextField s rauf und runter zu bewegen, wenn die Tastatur erscheint/verschwindet? Oder weiß jemand, warum meine Lösungen nicht funktioniert haben?

Antwort

0

Ich fand eine Lösung. Ich poste es für den Fall, dass jemand einmal dasselbe macht.

Also löschte ich die UIScrollView Steckdose in meiner Basisklasse und ersetzte sie durch eine einfache Eigenschaft, die ich in meinen erbenden Klassen festgelegt habe. Der Code für meine Basisklasse aussieht wie folgt:

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 
    } 
} 

Und hier ist der Vererbungsklassencode:

class ViewController: ScrollViewController { 

    @IBOutlet weak var scrollViewOutlet: UIScrollView! { 
     didSet { 
      self.scrollView = self.scrollViewOutlet 
     } 
    } 

    // Your view controller functions 

} 

Ich hoffe, das hilft!