Skip to content

Instantly share code, notes, and snippets.

@vialyx
Last active January 26, 2018 14:07
Show Gist options
  • Save vialyx/975e65b72dacf41c6c5a8e70d80800a2 to your computer and use it in GitHub Desktop.
Save vialyx/975e65b72dacf41c6c5a8e70d80800a2 to your computer and use it in GitHub Desktop.
//
// CactusKeyboard.swift
// CactusKeyboard
//
// Created by Maxim Vialykh on 1/26/18.
//
import UIKit
public typealias KeyboardCompletion = (Bool, CGFloat) -> Void
private class KeyboardObject {
let completion: KeyboardCompletion
init(_ completion: @escaping KeyboardCompletion) {
self.completion = completion
}
}
public protocol KeyboardCompletionProtocol {
func addKeyboardObserver(for observer: UIViewController, _ completion: @escaping KeyboardCompletion)
func removeKeyboardObserver(for observer: UIViewController)
}
public final class CactusKeyboard {
static let `default` = CactusKeyboard()
private var observers: NSMapTable<NSString, KeyboardObject> = NSMapTable(keyOptions: NSPointerFunctions.Options.strongMemory, valueOptions: NSPointerFunctions.Options.strongMemory)
private init() {
let center = NotificationCenter.default
center.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
center.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - Notifications
@objc private func keyboardWillShow(_ notification: Notification) {
var userInfo = notification.userInfo!
let keyboardFrame: CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
postCompletions(with: true, height: keyboardFrame.height)
}
@objc private func keyboardWillHide(_ notification: Notification) {
postCompletions(with: false, height: 0)
}
// MARK: - Inner
private func postCompletions(with visibility: Bool, height: CGFloat) {
guard let enumerator = observers.objectEnumerator() else { return }
enumerator.forEach {
if let object = $0 as? KeyboardObject {
object.completion(visibility, height)
}
}
}
}
// MARK: - KeyboardCompletionProtocol
extension CactusKeyboard: KeyboardCompletionProtocol {
public func addKeyboardObserver(for observer: UIViewController, _ completion: @escaping (Bool, CGFloat) -> Void) {
observers.setObject(KeyboardObject(completion), forKey: "\(type(of: observer))" as NSString)
}
public func removeKeyboardObserver(for observer: UIViewController) {
observers.removeObject(forKey: "\(observer)" as NSString)
}
}
// MARK: - Keyboard Observing
public extension UIViewController {
func addKeyboardObserver(_ completion: @escaping (Bool, CGFloat) -> Void) {
CactusKeyboard.default.addKeyboardObserver(for: self, completion)
}
func removeKeyboardObserver() {
CactusKeyboard.default.removeKeyboardObserver(for: self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment