swiftea
swiftea copied to clipboard
a simple example and some questions
I tried implementing a super simple example to get started:
struct SmokeStatus: Codable {
let isEnabled: Bool
}
enum SmokeMessage {
case smokeIsEnabled(_ flag: Bool)
}
typealias SmokeMessageHandler = MessageHandler<SmokeEnvironment, ApplicationModel.Smoke, SmokeMessage>
private let smokeIsEnabled: SmokeMessageHandler = .reducer { state, message in
guard
case let .smokeIsEnabled(flag) = message
else { return }
state.isEnabled = flag
}
let smokeMessageHandler = smokeIsEnabled
typealias SmokeCommand = Command<SmokeEnvironment, SmokeMessage>
enum SmokeCommands {
static let isEnabled = { (flag: Bool) -> SmokeCommand in
SmokeCommand { environment, publish in
publish(SmokeMessage.smokeIsEnabled(flag))
}
}
}
typealias SmokeEnvironment = SmokeServiceContainer
struct ApplicationModel: Codable {
enum CodingKeys: String, CodingKey {
case smoke
}
struct Smoke: Codable {
enum CodingKeys: String, CodingKey {
case isEnabled
}
var isEnabled: Bool = true
}
}
This is my view
struct SmokeViewBody: View {
var model: SmokeView.ViewModel
var body: some View {
Form {
Section() {
Toggle(isOn: model.isEnabled) {
Text("Notification:")
}
}
}
.navigationBarTitle("Quote of the day")
}
}
struct SmokeView: View {
struct ViewModel {
var isEnabled: Binding<Bool>
private let dispatcher: ApplicationStore.Dispatcher
init(smoke: ApplicationModel.Smoke, dispatcher: ApplicationStore.Dispatcher) {
self.dispatcher = dispatcher
self.isEnabled = Binding<Bool>(get: { () -> Bool in
smoke.isEnabled
}) { newValue in
dispatcher.send(SmokeCommands.isEnabled(newValue))
}
}
}
var body: some View {
ApplicationStateContainer(\.smoke) { smoke, dispatcher in
SmokeViewBody(model: ViewModel(smoke: smoke, dispatcher: dispatcher))
}
}
}
It works 👍
2019-09-30 21:41:06.372950+0200 Rework[17769:1105701] smokeIsEnabled(true)
2019-09-30 21:41:08.522575+0200 Rework[17769:1105283] smokeIsEnabled(false)
My questions:
- is this the right way to bind a simple value like a flag
- Why is it so laggy? It takes a second for the toggle to be updated.
- Should I use a @State so that the toggle is updated right away? Wouldn’t that defeat the purpose?
Take a look at @dynamicMemberLookup and @environmentObject...
/// The value referenced by the binding. Assignments to the value
/// will be immediately visible on reading (assuming the binding
/// represents a mutable location), but the view changes they cause
/// may be processed asynchronously to the assignment.
SwiftTEA should be able to do this.
I am really wondering now if a Redux or Elm like framework are really necessary for SwiftUI :
- [x] The SwiftUI views are read only.
- [x] Data flows one way either through
@environmentObjectwhich is really the application state or through a local state@statethat you can pass to children. - [x] Access control to the state can be enforced by making properties read-only and forcing mutation using methods.
- [x] SwiftUI takes care of the reducing and diffing
Am I missing something?