import Foundation import UIKit /// @brief A protocol that observes origin changes in a RNSSplitNavigationController’s view frame. /// /// The subscriber will be notified when the view's origin changes. protocol RNSSplitNavigationControllerViewFrameObserver: AnyObject { func splitNavCtrlViewDidChangeFrameOrigin( _ splitNavCtrl: RNSSplitNavigationController) } /// @class RNSSplitNavigationController /// @brief A subclass of UINavigationController, creates a view that wraps view associated with RNSSplitScreenController. /// /// This subclass is responsible for tracking when the underlying view's frame origin changes, /// allowing for syncing the ShadowTree layout. /// /// It observes origin changes via key-value observer and notifies a delegate. @objc public class RNSSplitNavigationController: UINavigationController { private var viewFrameObservation: NSKeyValueObservation? weak var viewFrameOriginChangeObserver: RNSSplitNavigationControllerViewFrameObserver? /// /// @brief Called after the view controller’s view has been loaded. /// /// Sets up a frame-origin Key-Value Observer to monitor view position changes and propagate them via delegate to RNSSplitHostController. /// override public func viewDidLoad() { super.viewDidLoad() viewFrameObservation?.invalidate() viewFrameObservation = self.view.observe(\.frame, options: [.old, .new]) { [weak self] (view, change) in guard let oldFrame = change.oldValue, let newFrame = change.newValue else { return } if oldFrame.origin != newFrame.origin { self?.onViewOriginChange() } } } private func onViewOriginChange() { viewFrameOriginChangeObserver?.splitNavCtrlViewDidChangeFrameOrigin(self) } }