Last active
June 17, 2017 15:54
-
-
Save sam-moshenko/064e03c1d0ef150de4aaf60473d844ae to your computer and use it in GitHub Desktop.
BaseViewController for iOS Swift to handle keyboard overlapping important views and easier translations between view controllers(IMHO)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// BaseVC.swift | |
// | |
// Created by Simon on 4/23/17. | |
// Copyright © 2017 Simon. All rights reserved. | |
// | |
import UIKit | |
/* | |
Paste here your format which you use | |
to identify StoryboardID for your VCs(View Controllers) | |
I recomend using StoryboardID which are the same as | |
naming of the class it uses | |
Paste '%@' where you have a real name of VC | |
For example if you have VCs named as: | |
TMLoginVC, TMRegisterVC, TMMenuVC | |
then you should use "TM%@VC" as your VCFormat | |
*/ | |
let VCFormat = "%@VC" | |
/* | |
List here all VCs' real names which you want to show from code | |
this name will be used with the VCFormat to constract a StoryboardID | |
*/ | |
enum VCs: String { | |
case Menu = "Menu" | |
} | |
class BaseVC: UIViewController, UITextFieldDelegate, UITextViewDelegate { | |
private var currentTextField: UIView? | |
/* | |
Assgin all textFields' and textViews' delegates | |
to viewController that inherits from the BaseVC | |
*/ | |
/* | |
Connect this constraint to a content view's top | |
to move all your content up when a keyboard appears | |
*/ | |
@IBOutlet weak var contentTopSpaceConstraint: NSLayoutConstraint? | |
private var initialTopSpace: CGFloat? | |
private var keyboardNotification: NSNotification? | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
self.initialTopSpace = self.contentTopSpaceConstraint?.constant | |
let tap = UITapGestureRecognizer.init(target: self, action: #selector(resignCurrentTextField)) | |
view.addGestureRecognizer(tap) | |
} | |
deinit { | |
NotificationCenter.default.removeObserver(self) | |
} | |
func getViewController(viewController: VCs) -> UIViewController { | |
let viewControllerName = String(format: VCFormat, viewController.rawValue) | |
return (storyboard?.instantiateViewController(withIdentifier: viewControllerName))! | |
} | |
func animateLayoutWithDuration(duration: Double, options: UIViewAnimationOptions) { | |
UIView.animate(withDuration: duration, delay: 0.0, options: options, animations: { | |
self.view.layoutIfNeeded() | |
}, completion: nil) | |
} | |
// MARK: Keyboard handling | |
@IBAction func resignCurrentTextField(sender: NSObject) { | |
if currentTextField != nil { | |
currentTextField?.resignFirstResponder() | |
} | |
} | |
func registerForKeyboardEvents() { | |
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), | |
name: .UIKeyboardWillHide, object: nil) | |
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotification), | |
name: .UIKeyboardWillShow, object: nil) | |
} | |
func handleKeyboardNotification(notification: NSNotification) { | |
let keyboardRect = view.convert((notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue, from: nil) | |
let curve = (notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).uintValue | |
let duration = (notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue | |
let animationCurveOption = curve << 16 | |
let textFieldFrame = view.convert((self.currentTextField?.frame)!, from: currentTextField?.superview) | |
if notification.name == .UIKeyboardWillShow { | |
let difference = textFieldFrame.maxY - keyboardRect.origin.y | |
if difference > 0 { | |
contentTopSpaceConstraint?.constant = self.initialTopSpace! - difference - 8.0 | |
} | |
self.keyboardNotification = notification | |
} else { | |
contentTopSpaceConstraint?.constant = self.initialTopSpace! | |
self.keyboardNotification = nil | |
} | |
animateLayoutWithDuration(duration: duration, options: UIViewAnimationOptions(rawValue: animationCurveOption)) | |
} | |
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { | |
currentTextField = textField | |
if keyboardNotification != nil { | |
handleKeyboardNotification(notification: keyboardNotification!) | |
} | |
return true | |
} | |
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { | |
currentTextField = textView | |
if keyboardNotification != nil { | |
handleKeyboardNotification(notification: keyboardNotification!) | |
} | |
return true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment