rickclephas / KMP-NativeCoroutines

Library to use Kotlin Coroutines from Swift code in KMP apps
MIT License
1.07k stars 32 forks source link

Thread frozen on ALPHA-15 and Combine #131

Closed leandrofavarin closed 1 year ago

leandrofavarin commented 1 year ago

I believe there's a regression from https://github.com/rickclephas/KMP-NativeCoroutines/pull/126. In my case I'm creating a Publisher from a SwiftUI View initialiser, like so:

struct PresentView<Content: View, ModelT>: View {
  @State var model: ModelT
  @State private var models: AnyPublisher<Any, Never> // https://github.com/rickclephas/KMP-NativeCoroutines/issues/90
  private let content: (ModelT) -> Content

  init(presenter: Presenter<ModelT>, content: @escaping (ModelT) -> Content) {
    ...
    self.models = createPublisher(for: presenter.__modelsFlow)
      .assertNoFailure()
      .eraseToAnyPublisher()
    self.content = content
  }

  var body: some View {
    content(model)
      .onReceive(models) { self.model = $0 as! ModelT }
  }
}

This didn't happen on ALPHA-14.

rickclephas commented 1 year ago

Thanks for reporting this, unfortunately I wasn't able to reproduce this. The following seems to work:

struct ClockView: View {

    @State var state: KotlinLong = 0
    @State var publisher: AnyPublisher<KotlinLong, Never>
    private let content: (KotlinLong) -> Text

    init() {
        publisher = createPublisher(for: Clock().time).assertNoFailure().eraseToAnyPublisher()
        content = { Text("\($0)") }
    }

    var body: some View {
        content(state)
            .onReceive(publisher) { self.state = $0 }
    }
}

Could you possible share a reproducer? Feel free to use the sample project.

leandrofavarin commented 1 year ago

I should have added one yesterday, sorry! You can find a repro here. 🙏

rickclephas commented 1 year ago

No problem! It seems only the following combination results in a thread freeze:

The reason being that there is always an initial value that is immediately send to the Swift callback. Fixed by making sure the Flow collection is started after the lock has been released.

rickclephas commented 1 year ago

FYI this has been fixed in v1.0.0-ALPHA-17.