slackhq / circuit

⚡️ A Compose-driven architecture for Kotlin and Android applications.
https://slackhq.github.io/circuit/
Apache License 2.0
1.5k stars 73 forks source link

Figure out iOS story with UI #650

Open ZacSweers opened 1 year ago

ZacSweers commented 1 year ago

Do we want to full on support Compose UI on iOS? Just presentation layer? Both?

ZacSweers commented 1 year ago

My current feeling is that we should try to focus on just Circuit in the presentation logic layer, then use native UI on iOS.

The sweet spot for this would be something along the lines of a Ui API that can abstract the underlying ContentView swift struct, perhaps a custom Ui.Factory that can look them up and connect them by screen. Really depends on what we can do with reflection or code gen in iOS to connect these pieces, or maybe every ContentView has to register itself with the original CircuitConfig somewhere manually for starters.

Currently our sample does something like this

struct ContentView: View {
  @ObservedObject var presenter = SwiftCounterPresenter()
  // ...
}

@MainActor
class SwiftCounterPresenter: BasePresenter<CounterScreenState> {
  init() {
    // TODO why can't swift infer these generics?
    super.init(
      delegate: SwiftSupportKt.asSwiftPresenter(SwiftSupportKt.doNewCounterPresenter())
        as! SwiftPresenter<CounterScreenState>)
  }
}

class BasePresenter<T: AnyObject>: ObservableObject {
  @Published var state: T? = nil

  init(delegate: SwiftPresenter<T>) {
    delegate.subscribe { state in
      self.state = state
    }
  }
}

It's likely that we'll want to pull in SwiftSupport.kt to Circuit runtime somewhere, as that gives us the compose -> callback hook needed to run in swift.

I think connecting these pieces will be tricky though, as CircuitContent internals would ultimately need to know if the underlying UI is a swift UI and switch to the SwiftSupport version instead, unless there's some other magic in SwiftUI that can ease this. Also - what about UIKit instead?

ZacSweers commented 1 year ago

I wonder if SKIE can help here https://touchlab.co/skie-is-open-source

ZacSweers commented 10 months ago

Simplified the iOS counter sample quite a bit. I think a good next step with it would be to add a switcher to the iOS UI to switch between compose and swift UI. Would be neat to make different versions of the patterns described here: https://www.jetbrains.com/help/kotlin-multiplatform-dev/compose-ios-ui-integration.html

RichWoollcott commented 10 months ago

Hi @ZacSweers, I recently did an experiment with using SKIE and just the Presenters and have just seen you have also now updated to use SKIE. It looks like we were doing the work at pretty much the same time!

It makes the code nicer on the Swift side.

One thing I also tried was the use of the DisplayLinkClock rather than the ImmediateClock - it might be worth looking into this also.

The code I experimented with is in this repo https://github.com/Appmilla/ComposablePresenterCounter

Thanks for the work you are doing on the iOS support - I realise this is beyond what you use Circuit for within Slack.

Personally, I would love to use Circuit for both native UI and shared UI on iOS and Android