I am trying to clean up my code and create and extension to UIViewController
to register and deregister my keyboard. In my utility file I have the following:
extension UIViewController {
//Register the keyboard for notifications in viewDidLoad
func registerForKeyboardNotifications() {
//Adding notifies on keyboard appearing
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CreateEventVC.keyboardWasShown(_:)), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CreateEventVC.keyboardWillBeHidden(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
//Deregister the keyboard for notification in viewWillDisapper
func deregisterFromKeyboardNotifications() {
//Removing notifies on keyboard appearing
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
}
What I need is the "CreateEventVC" in the selector
to be the current Class
.
Then I call it in my ViewController with the below:
override func viewDidLoad() {
super.viewDidLoad()
//Register Keyboard
registerForKeyboardNotifications()
}
override func viewWillDisappear(animated: Bool) {
deregisterFromKeyboardNotifications()
}
func keyboardWasShown(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y -= keyboardSize.height
}
}
func keyboardWillBeHidden(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
self.view.frame.origin.y += keyboardSize.height
}
}
I have a feeling this isn't the best practice. Any help or advice will be great!
I'm using UIViewController
and UIScrollView
extensions. If you're shifting your UIView
you also can use this extension, but using UIScrollView
is more convenient as it won't mess up with your view bounds and in case you need to add more textfields this approach is more generic.
extension UIViewController {
func registerForKeyboardDidShowNotification(usingBlock block: ((NSNotification, CGSize) -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
let userInfo = notification.userInfo!
guard let keyboardSize = userInfo[UIKeyboardFrameBeginUserInfoKey]?.CGRectValue.size else { fatalError("Can't grab the keyboard frame") }
block?(notification, keyboardSize)
})
}
func registerForKeyboardWillHideNotification(usingBlock block: (NSNotification -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillHideNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
block?(notification)
})
}
}
so with this code, in your UIViewController
's viewDidLoad()
method you can register for keyboards notifications and add any additional functions in blocks. Like this:
override func viewDidLoad() {
super.viewDidLoad()
registerForKeyboardDidShowNotification { notif, size in
self.view.frame.origin.y -= size.height
}
registerForKeyboardWillHideNotification { notif in
self.view.frame.origin.y = 0
}
}
UIScrollView
)1)Can you animate the keyboard showing?
Actually keyboard appearance is always animated, so i think you're saying about the scrollview adjustments. Yes, you can. Below I posted updated UIViewController
and UIScrollView
extensions, which are handling that.
2) Do i need to deregister the keyboard?
Well, it's a good practice to avoid crashes in the future. For that you probably may prefer to add your notification in viewWillAppear
and remove it in viewWillDisappear
methods.
NSNotificationCenter.defaultCenter().removeObserver(scrollView, name: UIKeyboardDidShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(scrollView, name: UIKeyboardWillHideNotification, object: nil)
3) For the UIScrollView method would I put all my objects in a scroll view in the screen then just programmatically scroll the view when each UITextField becomes the first responder?
You don't scroll anything programmatically. What you need to do is to change the insets of UIScrollView
and it will automatically make the firstResponder visible on the screen.
This is the code I use in my projects:
extension UIViewController {
func registerForKeyboardDidShowNotification(scrollView: UIScrollView, usingBlock block: (CGSize? -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
let userInfo = notification.userInfo!
let keyboardSize = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size
let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, keyboardSize!.height, scrollView.contentInset.right)
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
block?(keyboardSize)
})
}
func registerForKeyboardWillHideNotification(scrollView: UIScrollView, usingBlock block: (Void -> Void)? = nil) {
NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillHideNotification, object: nil, queue: nil, usingBlock: { (notification) -> Void in
let contentInsets = UIEdgeInsetsMake(scrollView.contentInset.top, scrollView.contentInset.left, 0, scrollView.contentInset.right)
scrollView.setContentInsetAndScrollIndicatorInsets(contentInsets)
block?()
})
}
}
extension UIScrollView {
func setContentInsetAndScrollIndicatorInsets(edgeInsets: UIEdgeInsets) {
self.contentInset = edgeInsets
self.scrollIndicatorInsets = edgeInsets
}
}
And in your viewWillAppear
method, just add it like this:
registerForKeyboardWillShowNotification(scrollView)
registerForKeyboardWillHideNotification(scrollView)
And it will shrink the scrollview's contentInset whenever the keyboard appears and expand it whenever keyboard disappears.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With