CI

swift-tca-loadable

一个 Swift 包,用于使用 The Composable Architecture 处理可加载项。

安装


使用 swift package manager 将此包安装到您的项目中。

let package = Package(
  ...
  dependencies: [
    ...
    .package(url: "https://github.com/m-housh/swift-tca-loadable.git", from: "0.2.0")
  ]
  ...
)

注意


0.3.+ 版本引入了与之前版本的不兼容性变更。 0.3.* 版本更新为使用 composable architecture 中的 Reducer

基本用法


此包提供了一个 LoadableView 以及几种在您的 Reducer 实现中使用的类型。

LoadableView

下面显示了一个示例 Reducer,并使用了 LoadableView

import ComposableArchitecture
import Loadable
import SwiftUI
 
struct App: Reducer {
  struct State: Equatable {
    @LoadableState var int: Int?
  }

  enum Action: Equatable, LoadableAction {
    case loadable(LoadingAction<Int>)
  }

  @Dependency(\.continuousClock) var clock;
  
  var body: some ReducerOf<Self> {
    Reduce { state, action in
      switch action {
      case .loadable(.load):
        return .load {
          /// sleep to act like data is loading from a remote.
          try await clock.sleep(for: .seconds(2))
          return 42
        }
      case .loadable:
        return .none
      }
    }
    .loadable(state: \.$int)
  }
}

struct ContentView: View {
  let store: StoreOf<App>
  var body: some View {
    VStack {
      LoadableView(store: store.scope(state: \.$int, action: Preview.Action.int)) {
        WithViewStore($0, observe: { $0 }) { viewStore in
          Text("Loaded: \(viewStore.state)")
        }
      Button(action: { ViewStore(store).send(.load) }) {
        Text("Reload")
      }
      .padding(.top)
    }
    .padding()
  }
}

上述代码在项目处于 notRequestedisLoading 状态时使用默认的 ProgressView,但您可以覆盖每个视图。

struct ContentView: View {

  let store: StoreOf<App>
    
  var body: some View {
    LoadableView(
      store: store.scope(state: \.$score, action: App.Action.int)
    ) { scoreStore in
      // The view when we have loaded content.
      WithViewStore(scoreStore) { viewStore in
        Text("Your score is: \(viewStore.state)")
      }
    } isLoading: { (isLoadingStore: Store<Int?, App.Action>) in 
      MyCustomIsLoadingView(store: isLoadingStore)
    } notRequested: { (notRequestedStore: Store<Void, App.Action>) in 
      MyCustomNotRequestedView(store: notRequestedStore)
    }
  }
}

文档


您可以在这里查看 API 文档。

Example Screenshot