From 7df92517613b040da58aa3e355ff2ca7417761e0 Mon Sep 17 00:00:00 2001 From: mapm14 Date: Sun, 21 Jan 2024 15:04:04 +0100 Subject: [PATCH] Create and pass LifecycleHelper from iOS apps to main.ios.kt --- demos/appyx-navigation/ios/build.gradle.kts | 2 + .../ios/src/iosMain/kotlin/main.ios.kt | 6 ++- .../iosApp/iosApp/ContentView.swift | 9 +++- .../iosApp/iosApp/iOSApp.swift | 37 +++++++++++++++- .../ios/build.gradle.kts | 2 + .../ios/src/iosMain/kotlin/main.ios.kt | 6 ++- .../iosApp/iosApp/ContentView.swift | 9 +++- .../iosApp/iosApp/iOSApp.swift | 43 +++++++++++++++++-- 8 files changed, 102 insertions(+), 12 deletions(-) diff --git a/demos/appyx-navigation/ios/build.gradle.kts b/demos/appyx-navigation/ios/build.gradle.kts index 63d859c17..a909f00e9 100644 --- a/demos/appyx-navigation/ios/build.gradle.kts +++ b/demos/appyx-navigation/ios/build.gradle.kts @@ -21,6 +21,7 @@ kotlin { framework { baseName = "ios" isStatic = true + export(project(":appyx-navigation:appyx-navigation")) } license = "Apache License, Version 2.0" authors = "https://github.com/bumble-tech/" @@ -36,6 +37,7 @@ kotlin { iosSimulatorArm64Main.dependsOn(this) dependencies { implementation(project(":demos:appyx-navigation:common")) + api(project(":appyx-navigation:appyx-navigation")) api(compose.runtime) api(compose.foundation) api(compose.material) diff --git a/demos/appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt b/demos/appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt index e63a1ef35..134a67fb4 100644 --- a/demos/appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt +++ b/demos/appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt @@ -12,6 +12,7 @@ import com.bumble.appyx.demos.navigation.node.root.RootNode import com.bumble.appyx.demos.navigation.ui.AppyxSampleAppTheme import com.bumble.appyx.navigation.integration.IosNodeHost import com.bumble.appyx.navigation.integration.MainIntegrationPoint +import com.bumble.appyx.navigation.platform.LifecycleHelper import kotlinx.coroutines.flow.flowOf import platform.Foundation.NSURL @@ -19,7 +20,7 @@ private val integrationPoint = MainIntegrationPoint() private val navigator = Navigator() @Suppress("FunctionNaming") -fun MainViewController() = ComposeUIViewController { +fun MainViewController(lifecycleHelper: LifecycleHelper) = ComposeUIViewController { AppyxSampleAppTheme { Scaffold( modifier = Modifier @@ -33,7 +34,8 @@ fun MainViewController() = ComposeUIViewController { IosNodeHost( modifier = Modifier, onBackPressedEvents = flowOf(), - integrationPoint = integrationPoint + integrationPoint = integrationPoint, + lifecycle = lifecycleHelper.lifecycle, ) { nodeContext -> RootNode( nodeContext = nodeContext, diff --git a/demos/appyx-navigation/iosApp/iosApp/ContentView.swift b/demos/appyx-navigation/iosApp/iosApp/ContentView.swift index 4fff14055..aedc9903c 100644 --- a/demos/appyx-navigation/iosApp/iosApp/ContentView.swift +++ b/demos/appyx-navigation/iosApp/iosApp/ContentView.swift @@ -3,16 +3,21 @@ import SwiftUI import ios struct ComposeView: UIViewControllerRepresentable { + + var lifecycleHelper: LifecycleHelper + func makeUIViewController(context: Context) -> UIViewController { - Main_iosKt.MainViewController() + Main_iosKt.MainViewController(lifecycleHelper: lifecycleHelper) } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} } struct ContentView: View { + var lifecycleHelper: LifecycleHelper + var body: some View { - ComposeView() + ComposeView(lifecycleHelper: lifecycleHelper) .ignoresSafeArea(.all) } } diff --git a/demos/appyx-navigation/iosApp/iosApp/iOSApp.swift b/demos/appyx-navigation/iosApp/iosApp/iOSApp.swift index 66023831a..86526af08 100644 --- a/demos/appyx-navigation/iosApp/iosApp/iOSApp.swift +++ b/demos/appyx-navigation/iosApp/iosApp/iOSApp.swift @@ -1,17 +1,52 @@ import SwiftUI import ios +import Foundation +import UIKit @main struct iOSApp: App { + + @UIApplicationDelegateAdaptor(AppDelegate.self) + var appDelegate: AppDelegate + + @Environment(\.scenePhase) var scenePhase + var body: some Scene { WindowGroup { ZStack { Color.white.ignoresSafeArea(.all) // status bar color - ContentView() + ContentView(lifecycleHelper: appDelegate.lifecycleHolder.lifecycleHelper) } .onOpenURL { incomingURL in Main_iosKt.handleDeepLinks(url: incomingURL) } + .onChange(of: scenePhase) { newPhase in + switch newPhase { + case .background: appDelegate.lifecycleHolder.lifecycleHelper.created() + case .inactive: appDelegate.lifecycleHolder.lifecycleHelper.created() + case .active: appDelegate.lifecycleHolder.lifecycleHelper.resumed() + @unknown default: break + } + } } } } + +class AppDelegate: NSObject, UIApplicationDelegate { + let lifecycleHolder: LifecycleHolder = LifecycleHolder() +} + +class LifecycleHolder { + + let lifecycleHelper: LifecycleHelper + + init() { + lifecycleHelper = LifecycleHelper() + lifecycleHelper.created() + } + + deinit { + // Destroy the root component before it is deallocated + lifecycleHelper.destroyed() + } +} diff --git a/demos/sandbox-appyx-navigation/ios/build.gradle.kts b/demos/sandbox-appyx-navigation/ios/build.gradle.kts index 5d55d2fdf..785b5f4d2 100644 --- a/demos/sandbox-appyx-navigation/ios/build.gradle.kts +++ b/demos/sandbox-appyx-navigation/ios/build.gradle.kts @@ -21,6 +21,7 @@ kotlin { framework { baseName = "ios" isStatic = true + export(project(":appyx-navigation:appyx-navigation")) } } @@ -34,6 +35,7 @@ kotlin { iosSimulatorArm64Main.dependsOn(this) dependencies { implementation(project(":demos:sandbox-appyx-navigation:common")) + api(project(":appyx-navigation:appyx-navigation")) api(compose.runtime) api(compose.foundation) api(compose.material) diff --git a/demos/sandbox-appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt b/demos/sandbox-appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt index 455f80b97..5a9d65cc9 100644 --- a/demos/sandbox-appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt +++ b/demos/sandbox-appyx-navigation/ios/src/iosMain/kotlin/main.ios.kt @@ -19,6 +19,7 @@ import com.bumble.appyx.demos.sandbox.navigation.node.container.MainNavNode import com.bumble.appyx.demos.sandbox.navigation.ui.AppyxSampleAppTheme import com.bumble.appyx.navigation.integration.IosNodeHost import com.bumble.appyx.navigation.integration.MainIntegrationPoint +import com.bumble.appyx.navigation.platform.LifecycleHelper import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.receiveAsFlow @@ -29,7 +30,7 @@ val backEvents: Channel = Channel() private val integrationPoint = MainIntegrationPoint() @Suppress("FunctionNaming") -fun MainViewController() = ComposeUIViewController { +fun MainViewController(lifecycleHelper: LifecycleHelper) = ComposeUIViewController { AppyxSampleAppTheme { val coroutineScope = rememberCoroutineScope() @@ -45,7 +46,8 @@ fun MainViewController() = ComposeUIViewController { IosNodeHost( modifier = Modifier, onBackPressedEvents = backEvents.receiveAsFlow(), - integrationPoint = remember { integrationPoint } + lifecycle = lifecycleHelper.lifecycle, + integrationPoint = remember { integrationPoint }, ) { nodeContext -> MainNavNode( nodeContext = nodeContext, diff --git a/demos/sandbox-appyx-navigation/iosApp/iosApp/ContentView.swift b/demos/sandbox-appyx-navigation/iosApp/iosApp/ContentView.swift index 4fff14055..aedc9903c 100644 --- a/demos/sandbox-appyx-navigation/iosApp/iosApp/ContentView.swift +++ b/demos/sandbox-appyx-navigation/iosApp/iosApp/ContentView.swift @@ -3,16 +3,21 @@ import SwiftUI import ios struct ComposeView: UIViewControllerRepresentable { + + var lifecycleHelper: LifecycleHelper + func makeUIViewController(context: Context) -> UIViewController { - Main_iosKt.MainViewController() + Main_iosKt.MainViewController(lifecycleHelper: lifecycleHelper) } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} } struct ContentView: View { + var lifecycleHelper: LifecycleHelper + var body: some View { - ComposeView() + ComposeView(lifecycleHelper: lifecycleHelper) .ignoresSafeArea(.all) } } diff --git a/demos/sandbox-appyx-navigation/iosApp/iosApp/iOSApp.swift b/demos/sandbox-appyx-navigation/iosApp/iosApp/iOSApp.swift index 1f23b442a..f2ce4003b 100644 --- a/demos/sandbox-appyx-navigation/iosApp/iosApp/iOSApp.swift +++ b/demos/sandbox-appyx-navigation/iosApp/iosApp/iOSApp.swift @@ -1,13 +1,50 @@ import SwiftUI +import ios +import Foundation +import UIKit @main struct iOSApp: App { + + @UIApplicationDelegateAdaptor(AppDelegate.self) + var appDelegate: AppDelegate + + @Environment(\.scenePhase) var scenePhase + var body: some Scene { WindowGroup { ZStack { Color.white.ignoresSafeArea(.all) // status bar color - ContentView() - }.preferredColorScheme(.light) + ContentView(lifecycleHelper: appDelegate.lifecycleHolder.lifecycleHelper) + } + .preferredColorScheme(.light) + .onChange(of: scenePhase) { newPhase in + switch newPhase { + case .background: appDelegate.lifecycleHolder.lifecycleHelper.created() + case .inactive: appDelegate.lifecycleHolder.lifecycleHelper.created() + case .active: appDelegate.lifecycleHolder.lifecycleHelper.resumed() + @unknown default: break + } + } } } -} \ No newline at end of file +} + +class AppDelegate: NSObject, UIApplicationDelegate { + let lifecycleHolder: LifecycleHolder = LifecycleHolder() +} + +class LifecycleHolder { + + let lifecycleHelper: LifecycleHelper + + init() { + lifecycleHelper = LifecycleHelper() + lifecycleHelper.created() + } + + deinit { + // Destroy the root component before it is deallocated + lifecycleHelper.destroyed() + } +}