Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ComposeUIViewController don't Update View #4781

Open
FelixSubject211 opened this issue May 8, 2024 · 2 comments
Open

ComposeUIViewController don't Update View #4781

FelixSubject211 opened this issue May 8, 2024 · 2 comments
Assignees
Labels
ios question Not a bug, but question or comment

Comments

@FelixSubject211
Copy link

Hello I have

fun SelectAppointmentViewController(
bookAppointmentScreenModel: BookAppointmentScreenModel,
appointmentBody: AppointmentBody
) = ComposeUIViewController {
MaterialTheme(colors = ColorSystem.ColorPalette()) {
SelectAppointmentCompose(bookAppointmentScreenModel, appointmentBody)
}
}

When I start the app in Android the SelectAppointmentCompose is updated. When the app starts from MainViewController in IOS also.

The problem occurs as soon as I call the SelectAppointmentCompose via the SelectAppointmentViewController in Swiftui. Then the compose is not redrawn with new calls, although SelectAppointmentViewController is called with new parameters

@FelixSubject211
Copy link
Author

I found a solution. It may well be that this isn't a bug at all. If so, I'm very sorry for the disruption!

You have to use the updateUIViewController in the calling UIViewControllerRepresentable.

I did it like this:

func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        let newViewController = SelectAppointmentViewControllerKt.SelectAppointmentViewController(
            bookAppointmentScreenModel: bookAppointmentScreenModel,
            appointmentBody: appointmentBody
        )
        
        uiViewController.willMove(toParent: nil)
        uiViewController.view.removeFromSuperview()
        uiViewController.removeFromParent()
        
        uiViewController.addChild(newViewController)
        newViewController.view.frame = uiViewController.view.frame
        uiViewController.view.addSubview(newViewController.view)
        newViewController.didMove(toParent: uiViewController)
 }

Felt a bit hacky but it worked

@elijah-semyonov
Copy link
Contributor

elijah-semyonov commented May 10, 2024

Sorry, I'm not exactly following what you are trying to achieve.
Can you create a repro and describe what is the expected behavior?

There is too much information missing.
Your updateUIViewController will recreate SelectAppointmentViewControllerKt.SelectAppointmentViewController every time the value of UIViewControllerRepresentable structure changes, which I don't think is something desired.
Plus creating a UIViewController inside a UIViewControllerRepresentable context is a bit novel?
Why not just use another UIViewControllerRepresentable?

The problem occurs as soon as I call the SelectAppointmentCompose via the SelectAppointmentViewController in SwiftUI.

This function creates a new UIViewController, that draws Composable content inside. In your case the Composable content is SelectAppointmentCompose(bookAppointmentScreenModel, appointmentBody). It will recalculate itself using the rules of Compose whenever values that affect the compose and are coming from bookAppointmentScreenModel and appointmentBody change (and the implementation actually reads or writes it). The state in there must be represented as compose.runtime.State (using mutableStateOf APIs and similar) otherwise Compose will not see them changing and hence won't be reacting.

Then the compose is not redrawn with new calls, although SelectAppointmentViewController is called with new parameters

It's not exactly clear what's happening in here. Do you mean, that parameters used by UIViewControllerRepresentable structure changed, but the ComposeUIViewController did not redraw? SwiftUI will try not to call makeUIViewController of UIViewControllerRepresentable unless it indeeds needs to make a new one and will only call updateUIViewController so you can update your data. In your case models should be created on Kotlin side and changed from within this callback, this way Compose will see the change in State and redraw accordingly.

@elijah-semyonov elijah-semyonov added question Not a bug, but question or comment and removed bug Something isn't working submitted uikit interop labels May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ios question Not a bug, but question or comment
Projects
None yet
Development

No branches or pull requests

3 participants