Tracking keyboard frame using Key value observing.


class TrackingView: UIView {

    var frameChanged: (() -> ())?

    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        guard let newSuperview = newSuperview else {return}
        newSuperview.addObserver(self, forKeyPath: "center", options: [.new, .old], context: nil)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard let object = object as? UIView, let superview = self.superview else {return}
        guard object === superview, let sChange = change else {return}
        let oldCenter = (sChange[NSKeyValueChangeKey.oldKey] as! NSValue).cgPointValue
        let newCenter = (sChange[NSKeyValueChangeKey.newKey] as! NSValue).cgPointValue
        guard oldCenter != newCenter else {return}
        frameChanged?()
    }

}


let trackingView = TrackingView()
textView.inputAccessoryView = trackingView
trackingView.frameChanged = {
    let convert = self.view.convert(trackingView.bounds, from: trackingView)
    self.textView(bottom: max(0, self.view.bounds.height - convert.maxY))
}