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

a simple example and some questions #10

Open
mycroftcanner opened this issue Sep 30, 2019 · 1 comment
Open

a simple example and some questions #10

mycroftcanner opened this issue Sep 30, 2019 · 1 comment
Assignees

Comments

@mycroftcanner
Copy link

mycroftcanner commented Sep 30, 2019

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:

  1. is this the right way to bind a simple value like a flag
  2. Why is it so laggy? It takes a second for the toggle to be updated.
  3. Should I use a @State so that the toggle is updated right away? Wouldn’t that defeat the purpose?
@kevinoneill kevinoneill self-assigned this Oct 2, 2019
@mycroftcanner
Copy link
Author

mycroftcanner commented Oct 2, 2019

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 :

  • The SwiftUI views are read only.
  • Data flows one way either through @environmentObject which is really the application state or through a local state @state that you can pass to children.
  • Access control to the state can be enforced by making properties read-only and forcing mutation using methods.
  • SwiftUI takes care of the reducing and diffing

Am I missing something?

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

No branches or pull requests

2 participants