Skip to content

Commit

Permalink
Replace KVO for measurer with bounds observer
Browse files Browse the repository at this point in the history
  • Loading branch information
mhoran committed Jan 3, 2025
1 parent e49f7cb commit 5d0e8a1
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 32 deletions.
13 changes: 13 additions & 0 deletions modules/keyboard-avoiding-view/ios/BoundsObservableView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
public class BoundsObservableView: UIView {
public weak var boundsDelegate: ViewBoundsObserving?
private var previousBounds: CGRect = .zero

public override func layoutSubviews() {
if bounds != previousBounds {
boundsDelegate?.boundsDidChange(self, from: previousBounds)
previousBounds = bounds
}

super.layoutSubviews()
}
}
41 changes: 9 additions & 32 deletions modules/keyboard-avoiding-view/ios/KeyboardAvoidingView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import ExpoModulesCore

// This view will be used as a native component. Make sure to inherit from `ExpoView`
// to apply the proper styling (e.g. border radius and shadows).
class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate {
private let measurer = UIView()
class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate, ViewBoundsObserving {
private let measurer = BoundsObservableView()
private let container = UIView()
private var scrollView: ScrollViewWrapper?
private var measurerHasObserver = false
private var isScrollViewPanning = false
private lazy var containerBottomAnchorConstraint: NSLayoutConstraint = {
return container.bottomAnchor.constraint(equalTo: bottomAnchor)
Expand All @@ -21,6 +20,7 @@ class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate {
addSubview(measurer)
measurer.translatesAutoresizingMaskIntoConstraints = false
measurer.isHidden = true
measurer.boundsDelegate = self

addSubview(container)
container.translatesAutoresizingMaskIntoConstraints = false
Expand Down Expand Up @@ -72,12 +72,6 @@ class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate {
}
}

deinit {
if measurerHasObserver {
measurer.removeObserver(self, forKeyPath: "center")
}
}

@objc private func keyboardWillShow(_ notification: Notification) {
guard notification.isLocalKeyboard else { return }

Expand All @@ -87,11 +81,6 @@ class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate {
@objc private func keyboardDidShow(_ notification: Notification) {
guard notification.isLocalKeyboard else { return }

// FIXME: don't use KVO
if !measurerHasObserver {
measurer.addObserver(self, forKeyPath: "center", options: .new, context: nil)
measurerHasObserver = true
}
isKeyboardShown = true
}

Expand Down Expand Up @@ -128,28 +117,16 @@ class KeyboardAvoidingView: ExpoView, UIGestureRecognizerDelegate {
@objc private func keyboardWillHide(_ notification: Notification) {
guard notification.isLocalKeyboard else { return }

if measurerHasObserver {
measurer.removeObserver(self, forKeyPath: "center")
measurerHasObserver = false
}
isKeyboardShown = false
updateInsets(notification, closing: true)
}

@objc override public func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey: Any]?,
context _: UnsafeMutableRawPointer?
) {
if keyPath == "center", object as? NSObject == measurer {
if !isScrollViewPanning {
return
}
self.scrollView?.setInsetsFromKeyboardHeight(measurer.frame.height)
self.containerBottomAnchorConstraint.constant = -measurer.frame.height
self.layoutIfNeeded()
}
func boundsDidChange(_ view: BoundsObservableView, from previousBounds: CGRect) {
guard isKeyboardShown && isScrollViewPanning else { return }

self.scrollView?.setInsetsFromKeyboardHeight(view.bounds.height)
self.containerBottomAnchorConstraint.constant = -view.bounds.height
self.layoutIfNeeded()
}

@objc func scrollViewPanned(gesture: UIPanGestureRecognizer) {
Expand Down
3 changes: 3 additions & 0 deletions modules/keyboard-avoiding-view/ios/ViewBoundsObserving.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
public protocol ViewBoundsObserving: AnyObject {
func boundsDidChange(_ view: BoundsObservableView, from previousBounds: CGRect)
}

0 comments on commit 5d0e8a1

Please sign in to comment.