Skip to content

Instantly share code, notes, and snippets.

@gfontenot
Created August 3, 2018 17:27
Show Gist options
  • Save gfontenot/2d6c2b66035c872a005c07e7b4622cae to your computer and use it in GitHub Desktop.
Save gfontenot/2d6c2b66035c872a005c07e7b4622cae to your computer and use it in GitHub Desktop.
Quick spike on an elm-ish architecture in Swift
// Dumb value types representing UIViews. Comperable to our current models like Button.Model
struct StackView<Message> {
let children: [View<Message>]
}
struct Label {
let text: String
}
struct Space {
let width: Int
}
struct TextField<Message> {
let text: String
}
// Generic type representing all available views. Cases aren't intended to be used directly
enum View<Message> {
case _stackView(StackView<Message>)
case _label(Label)
case _space(Space)
case _textField(TextField<Message>)
}
// Static functions for creating View instances. Takes any info needed and passes it through to the associated value
extension View {
static func stackView(_ children: [View<Message>]) -> View {
return ._stackView(StackView(children: children))
}
static func label(_ text: String) -> View {
return ._label(Label(text: text))
}
static func space(width: Int) -> View {
return ._space(Space(width: width))
}
static func textField(text: String) -> View {
return ._textField(TextField(text: text))
}
}
// A high level representation of a single component. Comperable to our current Presenter protocols
protocol Component {
// The state that the component cares about.
associatedtype Model
// Actions that can result in the state changing.
associatedtype Message
// Given a model, use this view heirarchy
static func view(_ model: Model) -> View<Message>
// Given a model and a message, return an updated model
static func update(_ model: Model, _ message: Message) -> Model
}
// A concrete representation of a single component, comperable to our current Presenter/ViewModel implementations
struct Calculator: Component {
struct Model {
let current: Int
}
enum Message {
case add(Int)
case subtract(Int)
}
static func view(_ model: Calculator.Model) -> View<Calculator.Message> {
return .stackView([
.stackView([
.label("Current Value"),
.label("\(model.current)"),
nameView("Gordon")
])
])
}
static func update(_ model: Calculator.Model, _ message: Calculator.Message) -> Calculator.Model {
switch message {
case let .add(n): return Model(current: model.current + n)
case let .subtract(n): return Model(current: model.current - n)
}
}
// An example of an extracted helper function for creating a smaller piece of the overall view.
private static func nameView(_ name: String) -> View<Message> {
return .stackView([
.label("Name"),
.space(width: 10),
.textField(text: name)
])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment