rive-app / rive-ios

iOS runtime for Rive
MIT License
468 stars 53 forks source link

Support SwiftUI style for managing animation state #260

Open ilyakuteev opened 1 year ago

ilyakuteev commented 1 year ago

The problem

Consider the following example (Taken from an app built using TCA):

struct SwiftUIView: View {
  var store: StoreOf<Feature>
  var animation = try! RiveViewModel(
    RiveModel(fileName: "Animation", in: .module)
  )
  var cancellables: Set<AnyCancellable> = []

  init(store: StoreOf< Feature >) {
    self. store = store

    // Problem here ❌
    ViewStore(store, observe: ViewState.init).publisher.sink { [animation] viewState in
      animation.setInput("Error", value: viewState.isError)
      animation.setInput("Success", value: viewState.isSuccess)
    }.store(in: &cancellables)
  }

  var body {
    animation.view()
  }
}

This example shows the problem while using Rive and SwiftUI together. Animation state is managed in UIKit-like control flow style.

Proposal

Add SwiftUI-like state management:

struct SwiftUIView: View {
  var store: StoreOf<Feature>
  var animation = try! RiveViewModel(
    RiveModel(fileName: "Animation", in: .module)
  )

  var body {
    WithViewStore(store) { viewStore in
       animation.view()
        .input("Error", value: viewState.isError)
        .input("Success", value: viewState.isSuccess)
    }
  }
}

In this case code gets simplier, animation state is now managed in view's body property and SwiftUI programming patterns are satisfied.