-
-
Save zddhub/77ffd275000970c9e99484ba6bdd8132 to your computer and use it in GitHub Desktop.
A SwiftUI based Playground for SwiftUI store management
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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