     // MARK: - Actions
 
     private func handleKeyboard(notification: NSNotification, _ action: KeyboardInfo.Action) {
+
         if let userInfo = notification.userInfo {
+
             let animationDuration: NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
             let animationCurve = (userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).unsignedLongValue
-            let frameBegin = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
             let frameEnd = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
 
             let currentHeight = frameEnd.height
-
             let previousHeight = keyboardInfo?.height ?? 0
             let heightIncrement = currentHeight - previousHeight
 
-            keyboardInfo = KeyboardInfo(frameBegin: frameBegin, frameEnd: frameEnd, animationDuration: animationDuration, animationCurve: animationCurve, heightIncrement: heightIncrement, action: action)
+            keyboardInfo = KeyboardInfo(animationDuration: animationDuration, animationCurve: animationCurve, frameEnd: frameEnd, heightIncrement: heightIncrement, action: action)
         }
     }
 
     func keyboardWillShow(notification: NSNotification) {
-        print("willShow\n")
+
         handleKeyboard(notification, .Show)
     }
     
     func keyboardDidChangeFrame(notification: NSNotification) {
+
         if let _ = keyboardInfo {
-            print("didChangeFrame\n")
             handleKeyboard(notification, .Show)
         }
     }
 
     func keyboardWillHide(notification: NSNotification) {
-        print("willHide\n")
+
         handleKeyboard(notification, .Hide)
+
+        // make sure `keyboardDidChangeFrame:` not work when hide
+
         keyboardInfo = nil
     }
-
-//    func keyboardDidHide(notification: NSNotification) {
-//        print("didHide\n")
-//        keyboardInfo = nil
-//    }
 }
 

            oldValue?.removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
            oldValue?.removeObserver(self, name: UIKeyboardDidChangeFrameNotification, object: nil)
            oldValue?.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
            //oldValue?.removeObserver(self, name: UIKeyboardDidHideNotification, object: nil)

            keyboardObserver?.addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
            keyboardObserver?.addObserver(self, selector: "keyboardDidChangeFrame:", name: UIKeyboardDidChangeFrameNotification, object: nil)
            keyboardObserver?.addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
            //keyboardObserver?.addObserver(self, selector: "keyboardDidHide:", name: UIKeyboardDidHideNotification, object: nil)
        }
    }


    }

    public struct KeyboardInfo {

        public let animationDuration: NSTimeInterval
        public let animationCurve: UInt

        let frameEnd: CGRect
        public var height: CGFloat {
            return frameEnd.height
        }
        public let heightIncrement: CGFloat

        public enum Action {
            case Show
            case Hide
        }
        public let action: Action
    }

    var keyboardInfo: KeyboardInfo? {
        willSet {
            if let info = newValue {
                updatedKeyboardInfo?(info)
            }
        }
