Skip to content

Instantly share code, notes, and snippets.

@antonyalkmim
Last active October 17, 2018 08:48
Show Gist options
  • Save antonyalkmim/700f085decf1f6a7d5f444a8fb0ecafa to your computer and use it in GitHub Desktop.
Save antonyalkmim/700f085decf1f6a7d5f444a8fb0ecafa to your computer and use it in GitHub Desktop.
iOS UIViewController extension to fix keyboard overriding textfield
//
// UIViewController+ext.swift
// Antony Alkmim
//
// Created by Antony Alkmim on 03/07/18.
// Copyright © 2018 Antony Alkmim. All rights reserved.
//
import UIKit
/// stored dataKeys
private var activeFieldAssocKey = 0
private var scrollViewAssocKey = 0
// MARK: - UITextFieldDelegate
extension UIViewController: UITextFieldDelegate {
public var activeField: UITextField? {
get { return objc_getAssociatedObject(self, &activeFieldAssocKey) as? UITextField }
set { objc_setAssociatedObject(self, &activeFieldAssocKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}
public func textFieldDidEndEditing(textField: UITextField) {
self.activeField = nil
}
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
self.activeField = textField
return true
}
public func textFieldShouldReturn(textField: UITextField) -> Bool {
guard let nextResponder = self.view.viewWithTag(textField.tag + 1) else {
textField.resignFirstResponder()
return false
}
nextResponder.becomeFirstResponder()
return false
}
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
// MARK: - UIScrollViewDelegate
extension UIViewController: UIScrollViewDelegate {
@IBOutlet var scrollView: UIScrollView? {
get { return objc_getAssociatedObject(self, &scrollViewAssocKey) as? UIScrollView }
set { objc_setAssociatedObject(self, &scrollViewAssocKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}
@objc func keyboardWillShow(notification: NSNotification) {
// Check if scrollView its referencied
guard self.scrollView != nil else { return }
if let activeField = self.activeField, let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
let contentInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: keyboardSize.height, right: 0.0)
self.scrollView!.contentInset = contentInsets
self.scrollView!.scrollIndicatorInsets = contentInsets
var aRect = self.view.frame
aRect.size.height -= keyboardSize.size.height //subtract keyboard height
if !aRect.contains(activeField.frame.origin) {
self.scrollView!.scrollRectToVisible(activeField.frame, animated: true)
}
}
}
@objc func keyboardWillBeHidden(notification: NSNotification) {
guard self.scrollView != nil else {return}
UIView.animate(withDuration: 0.17) {
self.scrollView!.contentInset = UIEdgeInsets.zero
self.scrollView!.scrollIndicatorInsets = UIEdgeInsets.zero
self.scrollView!.layoutIfNeeded()
}
}
func setupScrollKeyboard() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardWillShow),
name: NSNotification.Name.UIKeyboardDidShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardWillBeHidden),
name: NSNotification.Name.UIKeyboardDidHide,
object: nil)
}
}
extension UIScrollView {
override open func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.endEditing(true)
}
}
import UIKit
class ViewController: UIViewController {
// MARK: - Outlets
@IBOutlet weak var textfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textfield.delegate = self
setupScrollKeyboard()
textfield.becomeFirstResponder()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment