Skip to content

Instantly share code, notes, and snippets.

@Sjahriyar
Last active June 14, 2022 18:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Sjahriyar/916e93153a29dc602b45f29d39182352 to your computer and use it in GitHub Desktop.
Save Sjahriyar/916e93153a29dc602b45f29d39182352 to your computer and use it in GitHub Desktop.
class SomeClass: UIViewController
{
var firstResponder: UIView? /// To handle textField position when keyboard is visible.
var isKeyboardVisible = false /// You can handle tap on view by checking if keyboard is visible.
override func viewDidLoad() {
super.viewDidLoad()
/*
Register notifications for when keyboard appears/disappears
Note that we don't remove the observers if target iOS is iOS 9.0 or later
Apples Doc:
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method.
*/
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
@objc
fileprivate func keyboardNotification(_ notification: Notification) {
self.isKeyboardVisible.toggle()
if notification.name == UIResponder.keyboardWillShowNotification {
guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = keyboardValue.cgRectValue
// Note that textView delegate gets called later that keyboard notification unlike TextFields.
// So if firstResponder variable is nil it means our textView is firstRespnder.
if let textField = self.firstResponder ?? self.textView {
let textFieldPoints = textField.convert(textField.frame.origin, to: self.view.window)
let textFieldRect = textField.convert(textField.frame, to: self.view.window)
let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardFrame.height + textField.frame.height, right: 0)
self.scrollView.contentInset = contentInset
self.scrollView.scrollIndicatorInsets = contentInset
// visible part of the view, where is not covered by the keyboard.
var windowFrame = self.view.frame
windowFrame.size.height -= keyboardFrame.height
// if you don't see the firstResponder view in visible part, means the view is beneth the keyboard.
if !windowFrame.contains(textFieldPoints) {
self.scrollView.scrollRectToVisible(textFieldRect, animated: true)
}
}
}
if notification.name == UIResponder.keyboardWillHideNotification {
self.scrollView.contentInset = .zero
self.scrollView.scrollIndicatorInsets = .zero
}
}
}
// MARK: Delegates
extension SomeClass: UITextFieldDelegate
{
// MARK: TextField Delegate
func textFieldDidBeginEditing(_ textField: UITextField) {
self.firstResponder = textField // We set the firstResponder variable to active textField,
// This then will be handled in keyboardNotification()
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.firstResponder = nil
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment