@@ -13,54 +13,51 @@ private class Keyboard {
1313 var currentHeight : CGFloat = 0
1414}
1515
16- public extension UIView {
17-
16+ extension UIView {
1817 private enum AssociatedKeys {
1918 static var keyboardLayoutGuide = " keyboardLayoutGuide "
2019 }
21-
20+
2221 /// A layout guide representing the inset for the keyboard.
2322 /// Use this layout guide’s top anchor to create constraints pinning to the top of the keyboard.
24- var keyboardLayoutGuide : KeyboardLayoutGuide {
25- get {
26- if let obj = objc_getAssociatedObject ( self , & AssociatedKeys. keyboardLayoutGuide) as? KeyboardLayoutGuide {
27- return obj
28- }
29- let new = KeyboardLayoutGuide ( )
30- addLayoutGuide ( new)
31- new. setUp ( )
32- objc_setAssociatedObject ( self , & AssociatedKeys. keyboardLayoutGuide, new as Any , . OBJC_ASSOCIATION_RETAIN_NONATOMIC)
33- return new
23+ public var keyboardLayoutGuide : KeyboardLayoutGuide {
24+ if let obj = objc_getAssociatedObject ( self , & AssociatedKeys. keyboardLayoutGuide) as? KeyboardLayoutGuide {
25+ return obj
3426 }
27+ let new = KeyboardLayoutGuide ( )
28+ addLayoutGuide ( new)
29+ new. setUp ( )
30+ objc_setAssociatedObject ( self , & AssociatedKeys. keyboardLayoutGuide, new as Any , . OBJC_ASSOCIATION_RETAIN_NONATOMIC)
31+ return new
3532 }
3633}
3734
3835open class KeyboardLayoutGuide : UILayoutGuide {
39-
36+ @ available ( * , unavailable )
4037 public required init ? ( coder aDecoder: NSCoder ) {
4138 fatalError ( " init(coder:) has not been implemented " )
4239 }
43-
44- public override init ( ) {
40+
41+ public init ( notificationCenter : NotificationCenter = NotificationCenter . default ) {
4542 super. init ( )
46-
4743 // Observe keyboardWillChangeFrame notifications
48- let nc = NotificationCenter . default
49- nc. addObserver ( self ,
50- selector: #selector( keyboardWillChangeFrame ( _: ) ) ,
51- name: UIResponder . keyboardWillChangeFrameNotification,
52- object: nil )
44+ notificationCenter. addObserver (
45+ self ,
46+ selector: #selector( keyboardWillChangeFrame ( _: ) ) ,
47+ name: UIResponder . keyboardWillChangeFrameNotification,
48+ object: nil
49+ )
5350 }
54-
51+
5552 internal func setUp( ) {
56- guard let view = owningView else {
57- return
58- }
59- NSLayoutConstraint . activate ( [
60- heightAnchor . constraint ( equalToConstant : Keyboard . shared . currentHeight ) ,
61- leftAnchor . constraint ( equalTo: view. leftAnchor ) ,
62- rightAnchor . constraint ( equalTo : view . rightAnchor ) ,
63- ] )
53+ guard let view = owningView else { return }
54+ NSLayoutConstraint . activate (
55+ [
56+ heightAnchor . constraint ( equalToConstant : Keyboard . shared . currentHeight ) ,
57+ leftAnchor . constraint ( equalTo : view . leftAnchor ) ,
58+ rightAnchor . constraint ( equalTo: view. rightAnchor ) ,
59+ ]
60+ )
6461 let viewBottomAnchor : NSLayoutYAxisAnchor
6562 if #available( iOS 11 . 0 , * ) {
6663 viewBottomAnchor = view. safeAreaLayoutGuide. bottomAnchor
@@ -69,57 +66,52 @@ open class KeyboardLayoutGuide: UILayoutGuide {
6966 }
7067 bottomAnchor. constraint ( equalTo: viewBottomAnchor) . isActive = true
7168 }
72-
69+
7370 @objc
7471 private func keyboardWillChangeFrame( _ note: Notification ) {
7572 if var height = note. keyboardHeight {
76- if #available( iOS 11 . 0 , * ) , height > 0 {
77- height -= ( owningView ? . safeAreaInsets . bottom) !
73+ if #available( iOS 11 . 0 , * ) , height > 0 , let bottom = owningView ? . safeAreaInsets . bottom {
74+ height -= bottom
7875 }
7976 heightConstraint? . constant = height
8077 animate ( note)
8178 Keyboard . shared. currentHeight = height
8279 }
8380 }
84-
81+
8582 private func animate( _ note: Notification ) {
86- if isVisible ( view: self . owningView!) {
83+ if
84+ let owningView = self . owningView,
85+ isVisible ( view: owningView)
86+ {
8787 self . owningView? . layoutIfNeeded ( )
8888 } else {
8989 UIView . performWithoutAnimation {
9090 self . owningView? . layoutIfNeeded ( )
9191 }
9292 }
9393 }
94-
95- deinit {
96- NotificationCenter . default. removeObserver ( self )
97- }
9894}
9995
10096// MARK: - Helpers
10197
10298extension UILayoutGuide {
10399 internal var heightConstraint : NSLayoutConstraint ? {
104- guard let target = owningView else { return nil }
105- for c in target. constraints {
106- if let fi = c. firstItem as? UILayoutGuide , fi == self && c. firstAttribute == . height {
107- return c
108- }
100+ return owningView? . constraints. first {
101+ $0 == self && $0. firstAttribute == . height
109102 }
110- return nil
111103 }
112104}
113105
114106extension Notification {
115107 var keyboardHeight : CGFloat ? {
116- guard let v = userInfo ? [ UIResponder . keyboardFrameEndUserInfoKey] as? NSValue else {
108+ guard let keyboardFrame = userInfo ? [ UIResponder . keyboardFrameEndUserInfoKey] as? NSValue else {
117109 return nil
118110 }
119111 // Weirdly enough UIKeyboardFrameEndUserInfoKey doesn't have the same behaviour
120112 // in ios 10 or iOS 11 so we can't rely on v.cgRectValue.width
121113 let screenHeight = UIApplication . shared. keyWindow? . bounds. height ?? UIScreen . main. bounds. height
122- return screenHeight - v . cgRectValue. minY
114+ return screenHeight - keyboardFrame . cgRectValue. minY
123115 }
124116}
125117
@@ -136,4 +128,3 @@ func isVisible(view: UIView) -> Bool {
136128 }
137129 return isVisible ( view: view, inView: view. superview)
138130}
139-
0 commit comments