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

Figure out iOS story with UI #650

Open
ZacSweers opened this issue May 26, 2023 · 4 comments
Open

Figure out iOS story with UI #650

ZacSweers opened this issue May 26, 2023 · 4 comments
Labels
discussion Open discussions!

Comments

@ZacSweers
Copy link
Collaborator

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

@ZacSweers ZacSweers added the discussion Open discussions! label May 26, 2023
@ZacSweers
Copy link
Collaborator Author

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
Copy link
Collaborator Author

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

@ZacSweers
Copy link
Collaborator Author

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
Copy link

RichWoollcott commented Jan 10, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion Open discussions!
Projects
None yet
Development

No branches or pull requests

2 participants