From cf523b2ed9b946c396ba4e403653055848b6a1ac Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Fri, 4 Sep 2026 15:19:28 +0530 Subject: [PATCH 1/2] feat: migrate to scene based lifecycle --- CHANGELOG.md | 2 + .../project.pbxproj | 4 ++ .../ios/MendixNativeExample/AppDelegate.swift | 38 ++---------------- example/ios/MendixNativeExample/Info.plist | 17 ++++++++ .../MendixNativeExample/SceneDelegate.swift | 39 +++++++++++++++++++ example/ios/Podfile.lock | 8 ++-- ios/Modules/Helper/ReactAppProvider.swift | 38 ++++++++++++++---- ios/Modules/Helper/ReactHostHelper.mm | 2 +- 8 files changed, 101 insertions(+), 47 deletions(-) create mode 100644 example/ios/MendixNativeExample/SceneDelegate.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index cde843b..1d04fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- We migrated iOS to the UIKit scene-based life cycle. + ## [v0.5.2] - 2026-07-23 - We addressed a scenario where, in iOS, an Auth dialogue could continuously popup on app startup due to access of either large keychain blob items or blocked items. diff --git a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj index 8d0597b..59a47e5 100644 --- a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 1499ABBDB7935B67C3951198 /* libPods-MendixNativeExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 24A5FB93E78C6A91516539F4 /* libPods-MendixNativeExample.a */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; + 761780EF2CA45674006654EE /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EE2CA45674006654EE /* SceneDelegate.swift */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; E7824D7967CD7EE7C8E76686 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ @@ -22,6 +23,7 @@ 24A5FB93E78C6A91516539F4 /* libPods-MendixNativeExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MendixNativeExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 503B3921D3702B3C7DF3D941 /* Pods-MendixNativeExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MendixNativeExample.release.xcconfig"; path = "Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample.release.xcconfig"; sourceTree = ""; }; 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = MendixNativeExample/AppDelegate.swift; sourceTree = ""; }; + 761780EE2CA45674006654EE /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SceneDelegate.swift; path = MendixNativeExample/SceneDelegate.swift; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = MendixNativeExample/LaunchScreen.storyboard; sourceTree = ""; }; 9EF6D8952E93D80B00BFE8AE /* MendixNativeExample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MendixNativeExample-Bridging-Header.h"; sourceTree = ""; }; DC6440C7A3C29FAC4633A591 /* Pods-MendixNativeExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MendixNativeExample.debug.xcconfig"; path = "Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample.debug.xcconfig"; sourceTree = ""; }; @@ -49,6 +51,7 @@ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, 9EF6D8952E93D80B00BFE8AE /* MendixNativeExample-Bridging-Header.h */, + 761780EE2CA45674006654EE /* SceneDelegate.swift */, ); name = MendixNativeExample; sourceTree = ""; @@ -249,6 +252,7 @@ buildActionMask = 2147483647; files = ( 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + 761780EF2CA45674006654EE /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/example/ios/MendixNativeExample/AppDelegate.swift b/example/ios/MendixNativeExample/AppDelegate.swift index d86af0f..6ae8776 100644 --- a/example/ios/MendixNativeExample/AppDelegate.swift +++ b/example/ios/MendixNativeExample/AppDelegate.swift @@ -1,41 +1,9 @@ import UIKit -import React -import MendixNative @main -class AppDelegate: ReactAppProvider { +class AppDelegate: UIResponder, UIApplicationDelegate { - override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - setUpProvider() - guard let bundleUrl = bundleURL() else { - let message = "No script URL provided. Make sure the metro packager is running or you have embedded a JS bundle in your application bundle." - fatalError(message) - } - let mendixApp = MendixApp.init( - identifier: nil, - bundleUrl: bundleUrl, - runtimeUrl: URL(string: "http://localhost:8081")!, - warningsFilter: .none, - isDeveloperApp: true, - clearDataAtLaunch: false, - splashScreenPresenter: nil, - reactLoading: nil, - enableThreeFingerGestures: false - ) - - AppPreferences.devModeEnabled = true - AppPreferences.remoteDebuggingEnabled = true - - ReactNative.shared.setup(mendixApp, launchOptions: nil) - ReactNative.shared.start() - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } - - func bundleURL() -> URL? { - #if DEBUG - RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") - #else - Bundle.main.url(forResource: "main", withExtension: "jsbundle") - #endif + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool { + return true } } diff --git a/example/ios/MendixNativeExample/Info.plist b/example/ios/MendixNativeExample/Info.plist index d934e25..d7851ed 100644 --- a/example/ios/MendixNativeExample/Info.plist +++ b/example/ios/MendixNativeExample/Info.plist @@ -35,6 +35,23 @@ RCTNewArchEnabled + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/example/ios/MendixNativeExample/SceneDelegate.swift b/example/ios/MendixNativeExample/SceneDelegate.swift new file mode 100644 index 0000000..23562ab --- /dev/null +++ b/example/ios/MendixNativeExample/SceneDelegate.swift @@ -0,0 +1,39 @@ +import UIKit +import React +import MendixNative + +class SceneDelegate: ReactAppProvider { + + override func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + super.scene(scene, willConnectTo: session, options: connectionOptions) + + setUpProvider() + guard let bundleUrl = bundleURL() else { + let message = "No script URL provided. Make sure the metro packager is running or you have embedded a JS bundle in your application bundle." + fatalError(message) + } + let mendixApp = MendixApp.init( + identifier: nil, + bundleUrl: bundleUrl, + runtimeUrl: URL(string: "http://localhost:8081")!, + warningsFilter: .none, + isDeveloperApp: true, + clearDataAtLaunch: false, + splashScreenPresenter: nil, + reactLoading: nil, + enableThreeFingerGestures: false + ) + AppPreferences.devModeEnabled = true + AppPreferences.remoteDebuggingEnabled = true + ReactNative.shared.setup(mendixApp) + ReactNative.shared.start() + } + + func bundleURL() -> URL? { + #if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") + #else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") + #endif + } +} diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 2ca66db..12ad051 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2125,7 +2125,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: FBLazyVector: e97c19a5a442429d1988f182a1940fb08df514da - hermes-engine: 14f40a40d0d1d7bf76a9e3949a2bbebb33a817d7 + hermes-engine: a7179a4cd45fa3f8143712e52bd3c2d20b5274a0 MendixNative: b789c95cb7e776e332a0dabd4f39b91e20c1f31d op-sqlite: e9ef65bcf95a97863874cee87841425bb71c8396 OpenSSL-Universal: 9110d21982bb7e8b22a962b6db56a8aa805afde7 @@ -2137,7 +2137,7 @@ SPEC CHECKSUMS: React: 1ba7d364ade7d883a1ec055bfc3606f35fdee17b React-callinvoker: bc2a26f8d84fb01f003fc6de6c9337b64715f95b React-Core: 7840d3a80b43a95c5e80ef75146bd70925ebab0f - React-Core-prebuilt: 8e36d83999fd0789ad2551820a13d4af8b646369 + React-Core-prebuilt: a666604237ac1fb51754ee37234701cf197d851b React-CoreModules: 2eb010400b63b89e53a324ffb3c112e4c7c3ce42 React-cxxreact: a558e92199d26f145afa9e62c4233cf8e7950efe React-debug: 755200a6e7f5e6e0a40ff8d215493d43cce285fc @@ -2198,7 +2198,7 @@ SPEC CHECKSUMS: ReactAppDependencyProvider: e96e93b493d8d86eeaee3e590ba0be53f6abe46f ReactCodegen: 797de5178718324c6eba3327b07f9a423fbd5787 ReactCommon: 07572bf9e687c8a52fbe4a3641e9e3a1a477c78e - ReactNativeDependencies: f3a01ac658abdb7a6c6dc2e998074031fa8528a2 + ReactNativeDependencies: 9ed9fcba1a22047730c895521de699bacbb90312 RNCAsyncStorage: 3a4f5e2777dae1688b781a487923a08569e27fe4 RNGestureHandler: b4f6de20b30325ee40b693f558ad02213201ce91 SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef @@ -2206,4 +2206,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 115c3d28fbc33ec0a408f3aba951d5d16e47a401 -COCOAPODS: 1.17.0 +COCOAPODS: 1.15.2 diff --git a/ios/Modules/Helper/ReactAppProvider.swift b/ios/Modules/Helper/ReactAppProvider.swift index 9b73e91..1ee03bb 100644 --- a/ios/Modules/Helper/ReactAppProvider.swift +++ b/ios/Modules/Helper/ReactAppProvider.swift @@ -4,7 +4,7 @@ import React_RCTAppDelegate import ReactAppDependencyProvider @objcMembers -open class ReactAppProvider: UIResponder, UIApplicationDelegate { +open class ReactAppProvider: UIResponder, UIWindowSceneDelegate { public static let defaultName = "App" @@ -15,26 +15,50 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { var reactRootViewName: String = defaultName + private static weak var currentProvider: ReactAppProvider? + private var reactRootViewController: UIViewController? + + public var hasStartedReact: Bool { + return reactRootViewController != nil + } + public func setUpProvider( moduleName: String = ReactAppProvider.defaultName, reactRootViewName: String = ReactAppProvider.defaultName ) { self.moduleName = moduleName self.reactRootViewName = reactRootViewName + guard reactNativeFactory == nil else { + return + } let delegate = ReactNativeDelegate() let factory = RCTReactNativeFactory(delegate: delegate) delegate.dependencyProvider = RCTAppDependencyProvider() reactNativeDelegate = delegate reactNativeFactory = factory - window = UIWindow(frame: UIScreen.main.bounds) } - - open func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { - return true + + open func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + guard let windowScene = scene as? UIWindowScene else { + return + } + ReactAppProvider.currentProvider = self + window = UIWindow(windowScene: windowScene) + + if let reactRootViewController = reactRootViewController { + changeRoot(to: reactRootViewController) + } + } + + open func sceneDidDisconnect(_ scene: UIScene) { + if ReactAppProvider.currentProvider === self { + ReactAppProvider.currentProvider = nil + } } public func setReactViewController(_ controller: UIViewController) { controller.view = reactAppView() + reactRootViewController = controller changeRoot(to: controller) } @@ -43,7 +67,7 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { return nil } view.autoresizingMask = [.flexibleWidth, .flexibleHeight] - view.frame = window?.rootViewController?.view.frame ?? .zero + view.frame = window?.bounds ?? .zero return view } @@ -55,7 +79,7 @@ open class ReactAppProvider: UIResponder, UIApplicationDelegate { } public static func shared() -> ReactAppProvider? { - return UIApplication.shared.delegate as? ReactAppProvider + return currentProvider } public func changeRoot(to controller: UIViewController) { diff --git a/ios/Modules/Helper/ReactHostHelper.mm b/ios/Modules/Helper/ReactHostHelper.mm index f9ee17f..8eb159e 100644 --- a/ios/Modules/Helper/ReactHostHelper.mm +++ b/ios/Modules/Helper/ReactHostHelper.mm @@ -37,7 +37,7 @@ - (nullable id) getModuleForClass: (Class) clazz { } - (RCTHost *) currentHost { - ReactAppProvider *reactAppProvider = (ReactAppProvider *) [[UIApplication sharedApplication] delegate]; + ReactAppProvider *reactAppProvider = [ReactAppProvider shared]; RCTReactNativeFactory *reactNativeFactory = [reactAppProvider reactNativeFactory]; RCTRootViewFactory *rootViewFactory = [reactNativeFactory rootViewFactory]; RCTHost *reactHost = [rootViewFactory reactHost]; From 0141d71066f41ce4120551dab29563a8bf55ca35 Mon Sep 17 00:00:00 2001 From: Yogendra Shelke <25844542+YogendraShelke@users.noreply.github.com> Date: Mon, 7 Sep 2026 17:15:48 +0530 Subject: [PATCH 2/2] fix: respect launch options and improve URL handling --- .../project.pbxproj | 18 +++-- .../MendixNativeExample/SceneDelegate.swift | 2 +- example/ios/Podfile | 10 +++ example/ios/Podfile.lock | 2 +- ios/Modules/Helper/ReactAppProvider.swift | 73 ++++++++++++++++++- ios/Modules/ReactNative.swift | 10 ++- 6 files changed, 102 insertions(+), 13 deletions(-) diff --git a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj index 59a47e5..21408d6 100644 --- a/example/ios/MendixNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/MendixNativeExample.xcodeproj/project.pbxproj @@ -196,10 +196,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-frameworks.sh\"\n"; @@ -235,10 +239,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-resources-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-resources-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MendixNativeExample/Pods-MendixNativeExample-resources.sh\"\n"; @@ -389,10 +397,7 @@ "-DFOLLY_HAVE_CLOCK_GETTIME=1", "-DRCT_REMOVE_LEGACY_ARCH=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; @@ -467,10 +472,7 @@ "-DFOLLY_HAVE_CLOCK_GETTIME=1", "-DRCT_REMOVE_LEGACY_ARCH=1", ); - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; SWIFT_ENABLE_EXPLICIT_MODULES = NO; diff --git a/example/ios/MendixNativeExample/SceneDelegate.swift b/example/ios/MendixNativeExample/SceneDelegate.swift index 23562ab..139e837 100644 --- a/example/ios/MendixNativeExample/SceneDelegate.swift +++ b/example/ios/MendixNativeExample/SceneDelegate.swift @@ -25,7 +25,7 @@ class SceneDelegate: ReactAppProvider { ) AppPreferences.devModeEnabled = true AppPreferences.remoteDebuggingEnabled = true - ReactNative.shared.setup(mendixApp) + ReactNative.shared.setup(mendixApp, launchOptions: ReactAppProvider.launchOptions(from: connectionOptions)) ReactNative.shared.start() } diff --git a/example/ios/Podfile b/example/ios/Podfile index a31e654..6d139ba 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -37,5 +37,15 @@ target 'MendixNativeExample' do :mac_catalyst_enabled => false, # :ccache_enabled => true ) + + minimum_ios_version = Gem::Version.new(min_ios_version_supported) + installer.pods_project.targets.each do |target| + target.build_configurations.each do |build_configuration| + deployment_target = build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] + if deployment_target && Gem::Version.new(deployment_target) < minimum_ios_version + build_configuration.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = min_ios_version_supported + end + end + end end end diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 12ad051..212459d 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2204,6 +2204,6 @@ SPEC CHECKSUMS: SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef Yoga: c0b3f2c7e8d3e327e450223a2414ca3fa296b9a2 -PODFILE CHECKSUM: 115c3d28fbc33ec0a408f3aba951d5d16e47a401 +PODFILE CHECKSUM: 0cee92783ebe27187df65ef7b23a6a340d1aa921 COCOAPODS: 1.15.2 diff --git a/ios/Modules/Helper/ReactAppProvider.swift b/ios/Modules/Helper/ReactAppProvider.swift index 1ee03bb..24b1307 100644 --- a/ios/Modules/Helper/ReactAppProvider.swift +++ b/ios/Modules/Helper/ReactAppProvider.swift @@ -56,14 +56,83 @@ open class ReactAppProvider: UIResponder, UIWindowSceneDelegate { } } + open func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { + forwardURLContextsToReact(URLContexts) + } + + public func handleURLContexts( + _ URLContexts: Set, + whenReactInactive: ([AnyHashable: Any]) -> Void + ) { + if ReactAppProvider.isReactAppActive() { + forwardURLContextsToReact(URLContexts) + } else if let context = URLContexts.first { + whenReactInactive(ReactAppProvider.launchOptions(fromURLContext: context)) + } + } + + open func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + RCTLinkingManager.application( + UIApplication.shared, + continue: userActivity, + restorationHandler: { _ in } + ) + } + + public static func launchOptions(from connectionOptions: UIScene.ConnectionOptions) -> [AnyHashable: Any] { + var launchOptions: [AnyHashable: Any] = [:] + if let context = connectionOptions.urlContexts.first { + launchOptions.merge(ReactAppProvider.launchOptions(fromURLContext: context)) { _, new in new } + } + if let userActivity = connectionOptions.userActivities.first { + launchOptions[UIApplication.LaunchOptionsKey.userActivityDictionary] = [ + UIApplication.LaunchOptionsKey.userActivityType: userActivity.activityType, + "UIApplicationLaunchOptionsUserActivityKey": userActivity + ] as [AnyHashable: Any] + } + return launchOptions + } + + public static func launchOptions(fromURLContext context: UIOpenURLContext) -> [AnyHashable: Any] { + var launchOptions: [AnyHashable: Any] = [ + UIApplication.LaunchOptionsKey.url: context.url + ] + launchOptions[UIApplication.LaunchOptionsKey.sourceApplication] = context.options.sourceApplication + launchOptions[UIApplication.LaunchOptionsKey.annotation] = context.options.annotation + return launchOptions + } + + private func forwardURLContextsToReact(_ URLContexts: Set) { + URLContexts.forEach { context in + var options: [UIApplication.OpenURLOptionsKey: Any] = [ + .openInPlace: context.options.openInPlace + ] + options[.sourceApplication] = context.options.sourceApplication + options[.annotation] = context.options.annotation + RCTLinkingManager.application(UIApplication.shared, open: context.url, options: options) + } + } + public func setReactViewController(_ controller: UIViewController) { - controller.view = reactAppView() + setReactViewController(controller, launchOptions: nil) + } + + public func setReactViewController(_ controller: UIViewController, launchOptions: [AnyHashable: Any]?) { + controller.view = reactAppView(launchOptions: launchOptions) reactRootViewController = controller changeRoot(to: controller) } public func reactAppView() -> UIView? { - guard let view = reactNativeFactory?.rootViewFactory.view(withModuleName: reactRootViewName) else { + return reactAppView(launchOptions: nil) + } + + public func reactAppView(launchOptions: [AnyHashable: Any]?) -> UIView? { + guard let view = reactNativeFactory?.rootViewFactory.view( + withModuleName: reactRootViewName, + initialProperties: nil, + launchOptions: launchOptions + ) else { return nil } view.autoresizingMask = [.flexibleWidth, .flexibleHeight] diff --git a/ios/Modules/ReactNative.swift b/ios/Modules/ReactNative.swift index 5f3268c..bd02fd1 100644 --- a/ios/Modules/ReactNative.swift +++ b/ios/Modules/ReactNative.swift @@ -10,6 +10,7 @@ open class ReactNative: NSObject, RCTReloadListener { // MARK: - Properties private var mendixApp: MendixApp? private var bundleUrl: URL? + private var launchOptions: [AnyHashable: Any]? private var mendixOTAEnabled: Bool = false private var tapGestureHelper: TapGestureRecognizerHelper? @@ -26,6 +27,7 @@ open class ReactNative: NSObject, RCTReloadListener { public func setup(_ mendixApp: MendixApp, launchOptions: [AnyHashable: Any]? = nil, mendixOTAEnabled: Bool = false) { self.mendixApp = mendixApp self.bundleUrl = mendixApp.bundleUrl + self.launchOptions = launchOptions self.mendixOTAEnabled = mendixOTAEnabled if let host = bundleUrl?.host, let port = bundleUrl?.port { @@ -46,7 +48,13 @@ open class ReactNative: NSObject, RCTReloadListener { StorageHelper.clearAll() } - ReactAppProvider.shared()?.setReactViewController(mendixApp.reactLoading?.instantiateInitialViewController() ?? UIViewController()) + if let reactAppProvider = ReactAppProvider.shared() { + reactAppProvider.setReactViewController( + mendixApp.reactLoading?.instantiateInitialViewController() ?? UIViewController(), + launchOptions: launchOptions + ) + launchOptions = nil + } DevHelper.setShakeToShowDevMenuEnabled(enabled: AppPreferences.devModeEnabled) DevHelper.setDebugMode(enabled: AppPreferences.devModeEnabled && AppPreferences.remoteDebuggingEnabled)