Skip to content

Instantly share code, notes, and snippets.

@zddhub
Last active May 17, 2024 05:27
Show Gist options
  • Save zddhub/77ffd275000970c9e99484ba6bdd8132 to your computer and use it in GitHub Desktop.
Save zddhub/77ffd275000970c9e99484ba6bdd8132 to your computer and use it in GitHub Desktop.
A SwiftUI based Playground for SwiftUI store management
//: A SwiftUI based Playground for SwiftUI store management
import SwiftUI
import PlaygroundSupport
import Observation
struct ContentView: View {
@State private var name: String = ""
@State private var title: String = ""
var body: some View {
VStack {
Button {
name = UUID().uuidString
title = UUID().uuidString
} label: {
Text("Click me")
}
MyInitializableView(name: name, title: title)
// .id(name)
MyView()
}
.frame(minWidth: 300, minHeight: 400)
}
}
class DataModel: ObservableObject {
@Published var name = "Some Name"
@Published var isEnabled = false
init(name: String = "Some Name", isEnabled: Bool = false) {
self.name = name
self.isEnabled = isEnabled
}
}
class Library {
var name = ""
init(name: String = "My library of books") {
let seconds = 4.0
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
self.name = name
print("Library Init: name = \(name)")
}
}
}
struct MyInitializableView: View {
let title: String
@State private var state: String = "Hello"
@StateObject private var model: DataModel
@State private var library: Library? = Library(name: "Init Library inline")
init(name: String, title: String) {
// SwiftUI ensures that the following initialization uses the
// closure only once during the lifetime of the view, so
// later changes to the view's name input have no effect.
_model = StateObject(wrappedValue: DataModel(name: name))
// self.model = DataModel(name: name) // Compiler error
// state = "Why don not update me" // The same with StateObject
print("MyInitializableView init")
self.title = title
}
var body: some View {
let _ = Self._printChanges()
VStack {
Text("Name: \(model.name)")
Text("title: \(title)")
Text("state: \(state)")
if let library {
Text(library.name)
}
}
.onAppear {
print("MyInitializableView onAppear")
state = "World"
}
.task {
print("MyInitializableView task")
library = Library(name: "Init Library in task")
}
}
}
struct MyView: View {
@StateObject private var model = DataModel(name: "My View inline")
@State private var title: String = ""
var body: some View {
Text(model.name)
Button("Change title") {
title = UUID().uuidString
}
MySubView(model: model, title: title)
.onChange(of: model.isEnabled) { oldValue, newValue in
title = UUID().uuidString
}
}
}
struct MySubView: View {
@ObservedObject var model: DataModel
let title: String
init(model: DataModel, title: String) {
print("MySubView init")
self.model = model
// self.model = DataModel(name: "MySubView init") // Will change model when init runs
// self._model = ObservedObject(wrappedValue: DataModel(name: "MySubView init _model")) // Will change model when init runs
self.title = title
}
var body: some View {
Group {
Text("MySubView title: \(title)")
Text("MySubView name: \(model.name)")
Toggle("Enabled", isOn: $model.isEnabled)
}
.task {
self.model.name = "From My subview task init"
}
}
}
PlaygroundPage.current.setLiveView(ContentView())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment