Skip to content

Instantly share code, notes, and snippets.

@VAndrJ
Created August 9, 2024 09:53
Show Gist options
  • Save VAndrJ/020579d21cb12236aeac4c86158346d5 to your computer and use it in GitHub Desktop.
Save VAndrJ/020579d21cb12236aeac4c86158346d5 to your computer and use it in GitHub Desktop.
ObservableObject vs Observable vs State MRE
import SwiftUI
import Observation
@main
struct TestObservableBindableApp: App {
@State var observableObjectModel = ObservableObjectModel()
@State var observableModel = ObservableModel()
var body: some Scene {
WindowGroup {
TabView {
ObservableObjectExampleView()
.environmentObject(observableObjectModel)
.tabItem {
Label("ObservableObject", systemImage: "pencil")
}
ObservableExampleView()
.environment(observableModel)
.tabItem {
Label("Observable", systemImage: "pencil")
}
StateExampleView()
.tabItem {
Label("State", systemImage: "pencil")
}
}
.onReceive(NotificationCenter.default.publisher(for: UIApplication.didReceiveMemoryWarningNotification)) { _ in
print()
}
}
}
}
struct StateExampleView: View {
@State var isSomeOtherDummyVisibleNotHere = false
@State var isTopVisible = false
var body: some View {
let _ = Self._printChanges()
VStack {
ToggleableView(isVisible: $isTopVisible)
TapMeView(text: "Not used in this View") {
print("Toggle isSomeOtherDummyVisibleNotHere")
isSomeOtherDummyVisibleNotHere.toggle()
}
TapMeView(text: "Pased from this View") {
print("Toggle isTopVisible")
isTopVisible.toggle()
}
}
.padding()
}
}
@Observable
class ObservableModel {
var isSomeOtherDummyVisibleNotHere = false
var isTopVisible = false
}
struct ObservableExampleView: View {
@Environment(ObservableModel.self) var model
var body: some View {
let _ = Self._printChanges()
VStack {
ToggleableView(isVisible: model.bindable.isTopVisible)
TapMeView(text: "Not used in this View") {
print("Toggle isSomeOtherDummyVisibleNotHere")
model.isSomeOtherDummyVisibleNotHere.toggle()
}
TapMeView(text: "Pased from this View") {
print("Toggle isTopVisible")
model.isTopVisible.toggle()
}
}
.padding()
}
}
class ObservableObjectModel: ObservableObject {
@Published var isSomeOtherDummyVisibleNotHere = false
@Published var isTopVisible = false
}
struct ObservableObjectExampleView: View {
@EnvironmentObject var model: ObservableObjectModel
var body: some View {
let _ = Self._printChanges()
VStack {
ToggleableView(isVisible: $model.isTopVisible)
TapMeView(text: "Not used in this View") {
print("Toggle isSomeOtherDummyVisibleNotHere")
model.isSomeOtherDummyVisibleNotHere.toggle()
}
TapMeView(text: "Pased from this View") {
print("Toggle isTopVisible")
model.isTopVisible.toggle()
}
}
}
}
struct ToggleableView: View {
@Binding private var isVisible: Bool
private let date: Date
init(isVisible: Binding<Bool>) {
self._isVisible = isVisible
self.date = Date()
print("\(Self.self) \(#function) \(date, formatter: dateFormatter)")
}
var body: some View {
let _ = Self._printChanges()
Text("\(Self.self) \(#function) \(date, formatter: dateFormatter)")
.padding(.all, 20)
.frame(maxWidth: .infinity)
.background(.green)
.opacity(isVisible ? 1 : 0)
}
}
struct TapMeView: View {
private let text: String
private let onTap: () -> Void
private let date: Date
init(text: String, onTap: @escaping () -> Void) {
self.text = text
self.onTap = onTap
self.date = Date()
print("\(Self.self) \(#function) \(date, formatter: dateFormatter)")
}
var body: some View {
let _ = Self._printChanges()
Text("\(text)\n\(Self.self) \(#function) \(date, formatter: dateFormatter)")
.shadow(color: .green, radius: 4)
.padding(.all, 20)
.frame(maxWidth: .infinity)
.background(colors.randomElement())
.onTapGesture(perform: onTap)
}
}
let colors: [Color] = [
.orange.opacity(0.4),
.yellow.opacity(0.4),
.red.opacity(0.4),
.pink.opacity(0.4),
.purple.opacity(0.4),
.blue.opacity(0.4),
.indigo.opacity(0.4),
.teal.opacity(0.4),
.cyan.opacity(0.4),
.white.opacity(0.4),
.black.opacity(0.4),
]
extension Observable where Self: AnyObject {
var bindable: Bindable<Self> {
@Bindable var bindableSelf = self
return $bindableSelf
}
}
extension DefaultStringInterpolation {
mutating func appendInterpolation(_ date: Date, formatter: DateFormatter) {
appendLiteral(formatter.string(from: date))
}
}
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .none
formatter.timeStyle = .long
return formatter
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment