|
01. Write your UIViewController class like this: |
|
|
|
import UIKit |
|
|
|
class UserProfileViewController: UIViewController { |
|
|
|
override func viewDidLoad() { |
|
super.viewDidLoad() |
|
self.hideKeyboardWhenTappedAround() |
|
addKeyboardObservers() |
|
} |
|
|
|
override func viewWillDisappear(_ animated: Bool) { |
|
super.viewWillDisappear(animated) |
|
removeKeyboardObservers() |
|
|
|
} |
|
} |
|
|
|
02. Create a class extension like this: |
|
|
|
|
|
|
|
|
|
import UIKit |
|
|
|
extension UIViewController { |
|
|
|
|
|
func hideKeyboardWhenTappedAround() { |
|
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard)) |
|
tap.cancelsTouchesInView = false |
|
view.addGestureRecognizer(tap) |
|
print ("hideKeyboardWhenTapped") |
|
} |
|
@objc func dismissKeyboard() { |
|
view.endEditing(true) |
|
print ("dismissKeyboard") |
|
} |
|
|
|
func addKeyboardObservers() { |
|
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) |
|
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) |
|
print ("addKeyboardObservers") |
|
} |
|
|
|
func removeKeyboardObservers() { |
|
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window) |
|
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window) |
|
print ("removeKeyboardObservers") |
|
} |
|
|
|
@objc func keyboardWillShow(notification: NSNotification) { |
|
if let userInfo = notification.userInfo { |
|
if let keyboardSize = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { |
|
print("Keyboard Size: \(keyboardSize)") |
|
let keyboardHeight = keyboardSize.size.height |
|
if let activeTextField = UIResponder.currentFirst() as? UITextField { |
|
if keyboardSize.contains(activeTextField.frame.origin) { |
|
UIView.animate(withDuration: 0.1, animations: { () -> Void in |
|
self.view.window?.frame.origin.y = -1 * keyboardHeight |
|
self.view.layoutIfNeeded() |
|
print("keyboardWillShow \(String(describing: self.view.window?.frame.origin.y))") |
|
}) |
|
} |
|
} |
|
} |
|
} |
|
|
|
} |
|
|
|
@objc func keyboardWillHide(notification: NSNotification) { |
|
UIView.animate(withDuration: 0.1, animations: { () -> Void in |
|
self.view.window?.frame.origin.y = 0 |
|
self.view.layoutIfNeeded() |
|
self.view.setNeedsUpdateConstraints() |
|
print("keyboardWillHide \(String(describing: self.view.window?.frame.origin.y))") |
|
}) |
|
} |
|
|
|
|
|
func textFieldDidBeginEditing(textField: UITextField) { |
|
print ("textFieldDidBeginEditing") |
|
} |
|
|
|
func textFieldDidEndEditing(textField: UITextField) { |
|
print ("textFieldDidEndEditing") |
|
} |
|
|
|
func resignTextFieldFirstResponders() { |
|
for textField in self.view.subviews where textField is UITextField { |
|
textField.resignFirstResponder() |
|
print ("resignTextFieldFirstResponders") |
|
} |
|
} |
|
|
|
|
|
} |
|
|
|
//To identify the textField with focus, you need to search for the object that has become a first responder. First responder object is the one one having focus for user input. |
|
public extension UIResponder { |
|
|
|
private struct Static { |
|
static weak var responder: UIResponder? |
|
} |
|
|
|
public static func currentFirst() -> UIResponder? { |
|
Static.responder = nil |
|
UIApplication.shared.sendAction(#selector(UIResponder._trap), to: nil, from: nil, for: nil) |
|
return Static.responder |
|
} |
|
|
|
@objc private func _trap() { |
|
Static.responder = self |
|
} |
|
} |