From 677fac574c7465b9f6251884553ff108ec71813b Mon Sep 17 00:00:00 2001 From: David Date: Thu, 9 Apr 2026 10:28:23 -0700 Subject: [PATCH 1/2] Fix UIViewControllerHierarchyInconsistency crash --- ios/AirshipEmbeddedViewWrapper.swift | 34 +++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/ios/AirshipEmbeddedViewWrapper.swift b/ios/AirshipEmbeddedViewWrapper.swift index 2d725d9a..218a64e0 100644 --- a/ios/AirshipEmbeddedViewWrapper.swift +++ b/ios/AirshipEmbeddedViewWrapper.swift @@ -39,10 +39,20 @@ public final class AirshipEmbeddedViewWrapper: UIView { public override func didMoveToWindow() { super.didMoveToWindow() - guard !self.isAdded else { return } - self.viewController.willMove(toParent: self.parentViewController()) - self.parentViewController().addChild(self.viewController) - self.viewController.didMove(toParent: self.parentViewController()) + + if self.window == nil { + if self.isAdded { + self.viewController.willMove(toParent: nil) + self.viewController.removeFromParent() + self.isAdded = false + } + return + } + + guard !self.isAdded, let parentVC = self.parentViewController() else { return } + self.viewController.willMove(toParent: parentVC) + parentVC.addChild(self.viewController) + self.viewController.didMove(toParent: parentVC) self.viewController.view.isUserInteractionEnabled = true isAdded = true } @@ -53,18 +63,16 @@ public final class AirshipEmbeddedViewWrapper: UIView { } } -extension UIView -{ - //Get Parent View Controller from any view - func parentViewController() -> UIViewController { +extension UIView { + func parentViewController() -> UIViewController? { var responder: UIResponder? = self - while !(responder is UIViewController) { - responder = responder?.next - if nil == responder { - break + while let r = responder { + if let vc = r as? UIViewController { + return vc } + responder = r.next } - return (responder as? UIViewController)! + return nil } } From 7ff01517f32311afae4eb6dc82d7cbf637bdb5e7 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 10 Apr 2026 19:05:11 -0700 Subject: [PATCH 2/2] Release 25.4.2 --- CHANGELOG.md | 7 +++++++ ios/AirshipReactNative.swift | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ec921ed..22daef97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # React Native Module 25.0.0 Changelog +## Version 25.4.2 - April 10, 2026 + +Patch release that fixes a `UIViewControllerHierarchyInconsistency` crash in the Airship embedded view wrapper on iOS when an embedded view is pushed and popped on a navigation stack. + +### Changes +- Fixed iOS embedded view wrapper to properly remove its hosted `UIHostingController` as a child view controller when its window is detached, avoiding a `UIViewControllerHierarchyInconsistency` crash on re-attachment. + ## Version 25.4.1 - March 26, 2026 Patch release that fixes an Xcode 26.4 Swift compiler crash affecting iOS builds. diff --git a/ios/AirshipReactNative.swift b/ios/AirshipReactNative.swift index 8255039f..668ec62d 100644 --- a/ios/AirshipReactNative.swift +++ b/ios/AirshipReactNative.swift @@ -39,7 +39,7 @@ public class AirshipReactNative: NSObject { AirshipProxy.shared } - public static let version: String = "25.4.0" + public static let version: String = "25.4.2" private let eventNotifier = EventNotifier() diff --git a/package.json b/package.json index acfcd5a2..61586366 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ua/react-native-airship", - "version": "25.4.1", + "version": "25.4.2", "description": "Airship plugin for React Native apps.", "source": "./src/index.tsx", "main": "./lib/module/index.js",