JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.27k stars 1.18k forks source link

rememberSaveable not being restored on iOS #4112

Closed DevSrSouza closed 10 months ago

DevSrSouza commented 10 months ago

Describe the bug rememberSaveable is not being restored after presenting a new viewController (in the sample, the UIImagePickerController).

Affected platforms Select one of the platforms below:

Versions

To Reproduce Steps and/or the code snippet to reproduce the behavior:

fun MainViewController() = ComposeUIViewController {
    val randomNumber = rememberSaveable {
        Random.nextInt()
    }
    Column {
        val rootViewController = LocalUIViewController.current
        val imagePicker = remember {
            ImagePicker(
                rootController = rootViewController
            )
        }
        Text(text = "$randomNumber")
        Button(onClick = {
            imagePicker.openCamera()
        }) {
            Text("Open camera")
        }
    }
}

internal class ImagePicker(
    private val rootController: UIViewController
) {
    private val pickerController = UIImagePickerController().apply {
        sourceType = UIImagePickerControllerSourceType.UIImagePickerControllerSourceTypeCamera
    }

    fun openCamera() {
        rootController.presentViewController(pickerController, true, null)
    }
}

Steps:

Expected behavior The text with the random number should be the same/restored

Screenshots https://github.com/JetBrains/compose-multiplatform/assets/29736164/3d249104-071c-42e3-8769-04eb6e659250

MatkovIvan commented 10 months ago

It's duplicate of #1932

Despite that mentioned issue is quite old, it's not actually forgotten - we're planning to support this as part of (partially) porting lifecycle packages, which is required for proper navigation support.

DevSrSouza commented 10 months ago

@MatkovIvan I thought that issue was not related to iOS it self.

It seems that a previous version for Compose iOS was working because was not disposing the Composition, based on the comments of this PR: https://github.com/JetBrains/compose-multiplatform-core/pull/747

MatkovIvan commented 10 months ago

It seems that a previous version for Compose iOS was working

Thanks for this note. There are a few corner cases here, previously it was a source of memory leaks. So, it's about two things:

  1. Correct lifecycle of the Compose
  2. Restoring rememberSaveable during Compose re-creation

(1) is not trivial problem of combinng GC and ARC, @elijah-semyonov and @ASalavei are working on it. (2) is duplicate, as I mentioned above

elijah-semyonov commented 10 months ago

Actually, the memory leak with determined but not too eager scene destruction is already implemented: https://github.com/JetBrains/compose-multiplatform-core/commit/e001c0834bf2104c769055ea6db56d1b22eadccd#diff-ecbf335e72ff3f67cd7b87edb287efad88f3088f4c6a71b450d98b14c867d132 It should act similar to DisposeOnLifecycleDestroyed, except we don't guarantee that ViewController is actually destroyed and its reference can't be stored somewhere to be presented in the hierarchy again, I guess we will add assertion about it when lifecycle library is ported to avoid a situation where logically destroyed ViewController (removed from the window and containment hierarchy) is still alive in terms of object lifetime.

okushnikov commented 4 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.