 public extension FormController {
 
     func resignResponders() {
-        for responder in responders {
-            responder.resignFirstResponder()
-        }
-    }
-
-    func accessoryViewForResponder(responder: UIResponder) -> UIView {
+        for inputView in inputViews {
+            inputView.resignFirstResponder()
+        }
+    }
+
+}
+
+// MARK: Actions
+@objc private extension FormController {
+
+    func donePressed() {
+        resignResponders()
+    }
+
+    func nextInputView() {
+        logger?.logDebug(message: String(format: "[%@] nextInputView", instanceType(self)))
+        let nextIdx = inputViews.index(of: currentInputView!)! + 1
+        let nextField = inputViews[nextIdx]
+        if !nextField.becomeFirstResponder() {
+            guard let currentInputView = currentInputView else {
+                fatalError("no current input view")
+            }
+            if !currentInputView.resignFirstResponder() && !currentInputView.endEditing(true) {
+                fatalError("could not end editing in input field")
+            } else {
+                nextField.becomeFirstResponder()
+            }
+        }
+    }
+
+    func previousTextField() {
+        logger?.logDebug(message: String(format: "[%@] previousTextField", instanceType(self)))
+        let previousIdx = inputViews.index(of: currentInputView!)! - 1
+        let previousField = inputViews[previousIdx]
+        if !previousField.becomeFirstResponder() {
+            guard let currentInputView = currentInputView else {
+                fatalError("no current input view")
+            }
+            if !currentInputView.resignFirstResponder() && !currentInputView.endEditing(true) {
+                fatalError("could not end editing in input field")
+            } else {
+                previousField.becomeFirstResponder()
+            }
+        }
+    }
+}
+
+// MARK: Private
+private extension FormController {
+
+    func accessoryViewForInputView(view: UIView) -> UIView {
         let previousButton = UIBarButtonItem(title: "Prev", style: .plain, target: self, action: #selector(previousTextField))
-        if let idx = responders.index(of: responder) {
+        if let idx = inputViews.index(of: view) {
             previousButton.isEnabled = idx > 0
         } else {
             previousButton.isEnabled = false
         }
-        let nextButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(nextTextField))
-        if let idx = responders.index(of: responder) {
-            nextButton.isEnabled = idx < responders.count - 1
+        let nextButton = UIBarButtonItem(title: "Next", style: .plain, target: self, action: #selector(nextInputView))
+        if let idx = inputViews.index(of: view) {
+            nextButton.isEnabled = idx < inputViews.count - 1
         } else {
             nextButton.isEnabled = false
         }


public class FormController: NSObject {

    fileprivate var responders: [UIResponder]!
    fileprivate var oldTextFieldDelegates: [UITextField: UITextFieldDelegate?] = [:]
    fileprivate var oldTextViewDelegates: [UITextView: UITextViewDelegate?] = [:]
    fileprivate var currentResponder: UIResponder?

    public init(responders: [UIResponder]) {
        super.init()
        self.responders = responders

        for responder in responders {
            if let textField = responder as? UITextField {
                oldTextFieldDelegates[textField] = textField.delegate
                textField.delegate = self
                textField.inputAccessoryView = accessoryViewForResponder(responder: textField)
                if responders.index(of: responder)! < responders.count - 1 {
                    textField.returnKeyType = .next
                } else {
                    textField.returnKeyType = .done
                }
            } else if let textView = responder as? UITextView {
                oldTextViewDelegates[textView] = textView.delegate
                textView.delegate = self
                textView.inputAccessoryView = accessoryViewForResponder(responder: textView)
                if responders.index(of: responder)! < responders.count - 1 {
                    textView.returnKeyType = .next
                } else {
                    textView.returnKeyType = .done
                }
            } else {
                fatalError("Unsupported responder type.")
            }
        }
    }

}

    }

}
