keyboard notifications handling

This commit is contained in:
Ivan Smolin 2016-12-12 17:40:43 +03:00
parent 9e4e9f0cf8
commit f60c2cc373
9 changed files with 313 additions and 1 deletions

View File

@ -32,6 +32,13 @@
788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */; };
789CC6081DE5835600F789D3 /* CursorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789CC6071DE5835600F789D3 /* CursorType.swift */; };
789CC60B1DE584F800F789D3 /* CursorType+Slice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789CC60A1DE584F800F789D3 /* CursorType+Slice.swift */; };
789F5A0C1DFECB71004A3694 /* UIViewAnimationCurve+AnimationOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A0B1DFECB71004A3694 /* UIViewAnimationCurve+AnimationOptions.swift */; };
789F5A121DFECD11004A3694 /* KeyboardDidNotificationValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A111DFECD11004A3694 /* KeyboardDidNotificationValues.swift */; };
789F5A141DFECD54004A3694 /* KeyboardNotificationValuesError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A131DFECD54004A3694 /* KeyboardNotificationValuesError.swift */; };
789F5A161DFECD82004A3694 /* KeyboardWillNotificationValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A151DFECD82004A3694 /* KeyboardWillNotificationValues.swift */; };
789F5A1B1DFECF2B004A3694 /* Notification+UIKeyboardInfoValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A1A1DFECF2B004A3694 /* Notification+UIKeyboardInfoValues.swift */; };
789F5A1E1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A1D1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift */; };
789F5A201DFECF9F004A3694 /* KeyboardNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789F5A1F1DFECF9F004A3694 /* KeyboardNotification.swift */; };
78A0FCC71DC366A10070B5E1 /* StoryboardProtocol+DefaultBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A0FCC51DC366A10070B5E1 /* StoryboardProtocol+DefaultBundle.swift */; };
78A0FCC81DC366A10070B5E1 /* StoryboardProtocol+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A0FCC61DC366A10070B5E1 /* StoryboardProtocol+Extensions.swift */; };
78A74EA91C6B373700FE9724 /* UIView+DefaultNibName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78A74EA81C6B373700FE9724 /* UIView+DefaultNibName.swift */; };
@ -100,6 +107,13 @@
788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+InstantiateViewController.swift"; sourceTree = "<group>"; };
789CC6071DE5835600F789D3 /* CursorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CursorType.swift; sourceTree = "<group>"; };
789CC60A1DE584F800F789D3 /* CursorType+Slice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CursorType+Slice.swift"; sourceTree = "<group>"; };
789F5A0B1DFECB71004A3694 /* UIViewAnimationCurve+AnimationOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewAnimationCurve+AnimationOptions.swift"; sourceTree = "<group>"; };
789F5A111DFECD11004A3694 /* KeyboardDidNotificationValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardDidNotificationValues.swift; sourceTree = "<group>"; };
789F5A131DFECD54004A3694 /* KeyboardNotificationValuesError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardNotificationValuesError.swift; sourceTree = "<group>"; };
789F5A151DFECD82004A3694 /* KeyboardWillNotificationValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardWillNotificationValues.swift; sourceTree = "<group>"; };
789F5A1A1DFECF2B004A3694 /* Notification+UIKeyboardInfoValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Notification+UIKeyboardInfoValues.swift"; sourceTree = "<group>"; };
789F5A1D1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NotificationCenter+RxKeyboardExtensions.swift"; sourceTree = "<group>"; };
789F5A1F1DFECF9F004A3694 /* KeyboardNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardNotification.swift; sourceTree = "<group>"; };
78A0FCC51DC366A10070B5E1 /* StoryboardProtocol+DefaultBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StoryboardProtocol+DefaultBundle.swift"; sourceTree = "<group>"; };
78A0FCC61DC366A10070B5E1 /* StoryboardProtocol+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "StoryboardProtocol+Extensions.swift"; sourceTree = "<group>"; };
78A74EA81C6B373700FE9724 /* UIView+DefaultNibName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIView+DefaultNibName.swift"; path = "LeadKit/Extensions/UIView/UIView+DefaultNibName.swift"; sourceTree = SOURCE_ROOT; };
@ -177,6 +191,8 @@
isa = PBXGroup;
children = (
78753E231DE58A5D006BC0FB /* CursorError.swift */,
789F5A131DFECD54004A3694 /* KeyboardNotificationValuesError.swift */,
789F5A1F1DFECF9F004A3694 /* KeyboardNotification.swift */,
);
path = Enums;
sourceTree = "<group>";
@ -184,6 +200,7 @@
78011AAE1D48B46100EA16A2 /* Structures */ = {
isa = PBXGroup;
children = (
789F5A101DFECCFE004A3694 /* KeyboardNotificationValues */,
78011AB11D48B53600EA16A2 /* Api */,
);
path = Structures;
@ -270,6 +287,39 @@
path = CursorType;
sourceTree = "<group>";
};
789F5A0A1DFECB52004A3694 /* UIViewAnimationCurve */ = {
isa = PBXGroup;
children = (
789F5A0B1DFECB71004A3694 /* UIViewAnimationCurve+AnimationOptions.swift */,
);
path = UIViewAnimationCurve;
sourceTree = "<group>";
};
789F5A101DFECCFE004A3694 /* KeyboardNotificationValues */ = {
isa = PBXGroup;
children = (
789F5A111DFECD11004A3694 /* KeyboardDidNotificationValues.swift */,
789F5A151DFECD82004A3694 /* KeyboardWillNotificationValues.swift */,
);
path = KeyboardNotificationValues;
sourceTree = "<group>";
};
789F5A191DFECF2B004A3694 /* Notification */ = {
isa = PBXGroup;
children = (
789F5A1A1DFECF2B004A3694 /* Notification+UIKeyboardInfoValues.swift */,
);
path = Notification;
sourceTree = "<group>";
};
789F5A1C1DFECF44004A3694 /* NotificationCenter */ = {
isa = PBXGroup;
children = (
789F5A1D1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift */,
);
path = NotificationCenter;
sourceTree = "<group>";
};
78A0FCC41DC366A10070B5E1 /* StoryboardProtocol */ = {
isa = PBXGroup;
children = (
@ -376,6 +426,9 @@
786D78E61D53C355006B2CEA /* Alamofire */,
7884DB9A1DC1432B00E52A63 /* UserDefaults */,
789CC6091DE584C000F789D3 /* CursorType */,
789F5A0A1DFECB52004A3694 /* UIViewAnimationCurve */,
789F5A191DFECF2B004A3694 /* Notification */,
789F5A1C1DFECF44004A3694 /* NotificationCenter */,
);
path = Extensions;
sourceTree = "<group>";
@ -623,6 +676,7 @@
7837F60F1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift in Sources */,
78CFEE541C5C45E500F50370 /* UIView+LoadFromNib.swift in Sources */,
78D4B5461DA64D49005B0764 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */,
789F5A141DFECD54004A3694 /* KeyboardNotificationValuesError.swift in Sources */,
7834236A1DB8D0E100A79643 /* StoryboardProtocol.swift in Sources */,
78CFEE521C5C45E500F50370 /* UITableView+CellRegistration.swift in Sources */,
78B0FC7F1C6B2C4D00358B64 /* Log.swift in Sources */,
@ -630,6 +684,7 @@
789CC60B1DE584F800F789D3 /* CursorType+Slice.swift in Sources */,
78753E2C1DE58BF9006BC0FB /* StaticCursor.swift in Sources */,
78D4B54A1DA64EAB005B0764 /* Any+TypeName.swift in Sources */,
789F5A201DFECF9F004A3694 /* KeyboardNotification.swift in Sources */,
78CFEE571C5C45E500F50370 /* StaticNibNameProtocol.swift in Sources */,
788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */,
787783671CA04D4A001CDC9B /* String+SizeCalculation.swift in Sources */,
@ -638,6 +693,7 @@
786D78EC1D53C46E006B2CEA /* AlamofireManager+Extensions.swift in Sources */,
78B0FC811C6B2CD500358B64 /* App.swift in Sources */,
78B036491DA562C30021D5CC /* CGImage+Template.swift in Sources */,
789F5A1E1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift in Sources */,
78753E301DE594B4006BC0FB /* MapCursor.swift in Sources */,
780D23461DA416F80084620D /* CGContext+Initializers.swift in Sources */,
95B39A861D9D51250057BD54 /* String+Localization.swift in Sources */,
@ -651,6 +707,8 @@
786D78E81D53C378006B2CEA /* AlamofireRequest+Extensions.swift in Sources */,
78C36F811D8021DD00E7EBEA /* UIColor+Hex.swift in Sources */,
78CFEE5B1C5C45E500F50370 /* ViewModelProtocol.swift in Sources */,
789F5A1B1DFECF2B004A3694 /* Notification+UIKeyboardInfoValues.swift in Sources */,
789F5A121DFECD11004A3694 /* KeyboardDidNotificationValues.swift in Sources */,
780D23431DA412470084620D /* CGImage+Alpha.swift in Sources */,
78CFEE5A1C5C45E500F50370 /* ViewHeightProtocol.swift in Sources */,
787682FA1CAD40C300532AB3 /* StaticEstimatedViewHeightProtocol.swift in Sources */,
@ -663,8 +721,10 @@
789CC6081DE5835600F789D3 /* CursorType.swift in Sources */,
78B0364B1DA61EDE0021D5CC /* CGImage+Crop.swift in Sources */,
78B036451DA561D00021D5CC /* CGImage+Utils.swift in Sources */,
789F5A0C1DFECB71004A3694 /* UIViewAnimationCurve+AnimationOptions.swift in Sources */,
78CFEE591C5C45E500F50370 /* StoryboardIdentifierProtocol.swift in Sources */,
78011AB31D48B53600EA16A2 /* ApiRequestParameters.swift in Sources */,
789F5A161DFECD82004A3694 /* KeyboardWillNotificationValues.swift in Sources */,
78B0FC7D1C6B2BE200358B64 /* LogFormatter.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -0,0 +1,31 @@
//
// KeyboardNotification.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import Foundation
/// A type representing an possible keyboard notifications emitted by notification center
/// with accociated keyboard notification values
///
/// - willShow: UIKeyboardWillShow notification
/// - didShow: UIKeyboardDidShow notification
/// - willHide: UIKeyboardWillHide notification
/// - didHide: UIKeyboardDidHide notification
/// - willChangeFrame: UIKeyboardWillChangeFrame notification
/// - didChangeFrame: UIKeyboardDidChangeFrame notification
public enum KeyboardNotification {
case willShow(notificationValues: KeyboardWillNotificationValues)
case didShow(notificationValues: KeyboardDidNotificationValues)
case willHide(notificationValues: KeyboardWillNotificationValues)
case didHide(notificationValues: KeyboardDidNotificationValues)
case willChangeFrame(notificationValues: KeyboardWillNotificationValues)
case didChangeFrame(notificationValues: KeyboardDidNotificationValues)
}

View File

@ -0,0 +1,19 @@
//
// KeyboardNotificationValuesErrors.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import Foundation
/// A type representing an possible errors that can be thrown during
/// initializing KeyboardWillNotificationValues or KeyboardDidNotificationValues
///
/// - failedToInit: failed to init notification values object from given notification
public enum KeyboardNotificationValuesError: Error {
case failedToInit(fromNotification: Notification)
}

View File

@ -0,0 +1,42 @@
//
// Notification+UIKeyboardInfoValues.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import Foundation
public extension Notification {
/// CGRect value for UIKeyboardFrameBeginUserInfoKey or nil
var keyboardFrameBegin: CGRect? {
return (userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
}
/// CGRect value for UIKeyboardFrameEndUserInfoKey or nil
var keyboardFrameEnd: CGRect? {
return (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
}
/// TimeInterval value for UIKeyboardAnimationDurationUserInfoKey or nil
var keyboardAnimationDuration: TimeInterval? {
return (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
}
/// UIViewAnimationCurve value for UIKeyboardAnimationDurationUserInfoKey or nil
var keyboardAnimationCurve: UIViewAnimationCurve? {
if let rawValue = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.intValue {
return UIViewAnimationCurve(rawValue: rawValue)
}
return nil
}
/// Bool value for UIKeyboardIsLocalUserInfoKey or nil
var keyboardIsLocal: Bool? {
return (userInfo?[UIKeyboardIsLocalUserInfoKey] as? NSNumber)?.boolValue
}
}

View File

@ -0,0 +1,54 @@
//
// NotificationCenter+Rx.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
extension Reactive where Base: NotificationCenter {
/// Observable of KeyboardNotification subscribed to all kinds of keyboard notifications
var keyboardNotifications: Observable<KeyboardNotification> {
let rxNotificationCenter = NotificationCenter.default.rx
let willShowObservable = rxNotificationCenter.notification(.UIKeyboardWillShow)
.map { notification -> KeyboardNotification in
return .willShow(notificationValues: try KeyboardWillNotificationValues(notification: notification))
}
let didShowObservable = rxNotificationCenter.notification(.UIKeyboardDidShow)
.map { notification -> KeyboardNotification in
return .didShow(notificationValues: try KeyboardDidNotificationValues(notification: notification))
}
let willHideObservable = rxNotificationCenter.notification(.UIKeyboardWillHide)
.map { notification -> KeyboardNotification in
return .willHide(notificationValues: try KeyboardWillNotificationValues(notification: notification))
}
let didHideObservable = rxNotificationCenter.notification(.UIKeyboardDidHide)
.map { notification -> KeyboardNotification in
return .didHide(notificationValues: try KeyboardDidNotificationValues(notification: notification))
}
let willChangeFrameObservable = rxNotificationCenter.notification(.UIKeyboardWillChangeFrame)
.map { notification -> KeyboardNotification in
return .willChangeFrame(notificationValues: try KeyboardWillNotificationValues(notification: notification))
}
let didChangeFrameObservable = rxNotificationCenter.notification(.UIKeyboardDidChangeFrame)
.map { notification -> KeyboardNotification in
return .didChangeFrame(notificationValues: try KeyboardDidNotificationValues(notification: notification))
}
return Observable.of(willShowObservable, didShowObservable,
willHideObservable, didHideObservable,
willChangeFrameObservable, didChangeFrameObservable).merge()
}
}

View File

@ -67,7 +67,6 @@ public extension UIColor {
self.init(red: red, green: green, blue: blue, alpha: alpha)
}
/**
convenience failable initializer which creates an instance with given hex color values if string has a correct format

View File

@ -0,0 +1,27 @@
//
// UIViewAnimationCurve+AnimationOptions.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import Foundation
public extension UIViewAnimationCurve {
/// UIViewAnimationOptions value matching current animation curve
var animationOptions: UIViewAnimationOptions {
switch self {
case .easeInOut:
return .curveEaseInOut
case .easeIn:
return .curveEaseIn
case .easeOut:
return .curveEaseOut
case .linear:
return .curveLinear
}
}
}

View File

@ -0,0 +1,38 @@
//
// KeyboardDidNotificationValues.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import UIKit
/// Struct which keeps values from one of those notifications:
/// UIKeyboardDidShow, UIKeyboardDidHide, UIKeyboardDidChangeFrame
public struct KeyboardDidNotificationValues {
let sizeBegin: CGSize
let sizeEnd: CGSize
let isLocal: Bool
// Animation key/value pairs are only available for the "will" family of notification. (UIWindow.h)
}
public extension KeyboardDidNotificationValues {
init(notification: Notification) throws {
guard let sizeBegin = notification.keyboardFrameBegin?.size,
let sizeEnd = notification.keyboardFrameEnd?.size,
let isLocal = notification.keyboardIsLocal else {
throw KeyboardNotificationValuesError.failedToInit(fromNotification: notification)
}
self.sizeBegin = sizeBegin
self.sizeEnd = sizeEnd
self.isLocal = isLocal
}
}

View File

@ -0,0 +1,42 @@
//
// KeyboardWillNotificationValues.swift
// LeadKit
//
// Created by Ivan Smolin on 12/12/16.
// Copyright © 2016 Touch Instinct. All rights reserved.
//
import UIKit
/// Struct which keeps values from one of those notifications:
/// UIKeyboardWillShow, UIKeyboardWillHide, UIKeyboardWillChangeFrame
public struct KeyboardWillNotificationValues {
let sizeBegin: CGSize
let sizeEnd: CGSize
let animationDuration: TimeInterval
let animationCurve: UIViewAnimationCurve
let isLocal: Bool
}
public extension KeyboardWillNotificationValues {
init(notification: Notification) throws {
guard let sizeBegin = notification.keyboardFrameBegin?.size,
let sizeEnd = notification.keyboardFrameEnd?.size,
let animationDuration = notification.keyboardAnimationDuration,
let animationCurve = notification.keyboardAnimationCurve,
let isLocal = notification.keyboardIsLocal else {
throw KeyboardNotificationValuesError.failedToInit(fromNotification: notification)
}
self.sizeBegin = sizeBegin
self.sizeEnd = sizeEnd
self.animationDuration = animationDuration
self.animationCurve = animationCurve
self.isLocal = isLocal
}
}