Releases: 0xOpenBytes/DataDrivenUI
0.2.0
What Changed?
ComposedView
protocol changed toComposableView
ViewProducing
'sRootView
changed toComposedView
ViewProducing
'srootView
changed toview
- Added counter test
Counter Test Example
struct CounterView: ComposableView {
struct Content {
let count: String
}
struct Capabilities {
let increment: () -> Void
let decrement: () -> Void
}
let content: Content
let capabilities: Capabilities
var body: some View {
VStack {
Text(content.count)
HStack {
Button(action: capabilities.decrement, label: { Text("-") })
Button(action: capabilities.increment, label: { Text("+") })
}
}
.padding()
}
}
class CounterViewModel: ViewProducing {
typealias ComposedView = CounterView
@Published private var count: Int = 0
var content: Content {
Content(
count: "\(count)"
)
}
var capabilities: Capabilities {
Capabilities(
increment: increment,
decrement: decrement
)
}
private func increment() {
count += 1
}
private func decrement() {
count -= 1
}
}
let counterViewModel = CounterViewModel()
XCTAssertEqual(counterViewModel.content.count, "0")
counterViewModel.capabilities.increment()
XCTAssertEqual(counterViewModel.content.count, "1")
counterViewModel.capabilities.decrement()
counterViewModel.capabilities.decrement()
XCTAssertEqual(counterViewModel.content.count, "-1")
Full Changelog: 0.1.0...0.2.0
0.1.0
DataDrivenUI
Producing Views from data since 2022
What is DataDrivenUI?
When did putting Classes in Structs become normal? Well, when did SwiftUI get released?
DataDrivenUI takes a data first approach, by focusing on how data is passed around. To be specific, DataDrivenUI reverses the idea of the ViewModel and View. Normally the View will own the ViewModel, a Struct owning a Class. DataDrivenUI creates a contract between the View and the object producing said View. The View determines what Content and Capabilities it needs to function. Then you can create objects that can create the needed Content and Capabilities the View needs. Doing this the View doesn't know what object produced it, but does have the needed Content and Capabilities it needs to work.
Example Usage
struct ExampleComposedView: ComposedView {
struct Content {
let name: String
}
struct Capabilities {
let updateName: (String) -> Void
}
var content: Content
var capabilities: Capabilities
var body: some View {
Text("Hello, \(content.name)!")
.onAppear {
capabilities.updateName("\(Date().timeIntervalSince1970)")
}
}
}
class ExampleViewProducer: ViewProducing {
typealias RootView = ExampleComposedView
@Published private var name: String = "Tests"
var content: Content {
Content(name: name)
}
var capabilities: Capabilities {
Capabilities(
updateName: update(name:)
)
}
private func update(name: String) {
self.name = name
}
}
let viewProducer = ExampleViewProducer()
XCTAssertEqual(viewProducer.content.name, "Tests")
viewProducer.capabilities.updateName("World")
XCTAssertEqual(viewProducer.content.name, "World")