An easy-reuse UIViewController extension to support making screen space for the keyboard, with minimal boilerplate code.
To use in any UIViewController, include this extension (KeyboardFriendly.swift
) in your project, then in each controller where you want this behavior, do the following:
-
Make sure the view is wrapped in a top-level UIScrollView, to allow the view to be moved.
-
Override the computed property:
var keyboardFriendlyScrollView: UIScrollView?
to return that scroll view. If this var returns
nil
(the default), keyboard-friendliness will not be activated. -
In
viewDidLoad
, callself.activateKeyboardFriendliness()
. -
In
deinit
, callself.deactivateKeyboardFriendliness()
.Alternatively, depending on the needs of the controller, put the activate and deactivate calls in
viewDidAppear
andviewDidDisappear
, respectively. That may be a better choice if the controller is still responding to keyboard events inappropriately while it's offscreen. -
Optional โ To auto-scroll the view to show the field being edited: Override the computed property:
var keyboardFriendlyKeepOnscreen: CGRect
to return the rect area of the current field, or any other rect that you want to keep onscreen. Return
CGRect.zero
(a.k.a.CGRectZero
) to suppress auto-scrolling.1Note that the rect must be in the scroll view's coordinate system! Use
UIView.convertRect:toView:
orUIView.convertRect:fromView:
if necessary.A simple, basic implementation will track the bounds of the first responder in a concrete instance variable, and have
keyboardFriendlyKeepOnscreen
return that variable's value:var firstResponderBounds: CGRect? override var keyboardFriendlyKeepOnscreen: CGRect { return self.firstResponderBounds ?? CGRect.zero }
Use
UITextFieldDelegate
to keep track of the first responder.
1Why use CGRect.zero
to mean "no scrolling" instead of returning an optional? Current Swift limitations
(2.2): declarations in an extension can only be overridden in the main class if they're marked @objc
,
but the CGRect?
type can't be represented in Objective-C code.