Skip to content

Instantly share code, notes, and snippets.

@alexobenauer
Last active June 11, 2019 14:23
Show Gist options
  • Save alexobenauer/8ba0182cf36b7f4025a9b34fa003086c to your computer and use it in GitHub Desktop.
Save alexobenauer/8ba0182cf36b7f4025a9b34fa003086c to your computer and use it in GitHub Desktop.
How EnvironmentObjects work in SwiftUI views
//
// SwiftUI-EnvironmentObjectExample.swift
// SwiftUI-DataFlowExamples
//
// Part of the series beginning at:
// https://medium.com/@alexobenauer/demystifying-data-flow-through-swiftui-697017aba7e0
//
import SwiftUI
import Combine
// This is a simple example of a class conforming to the
// BindableObject protocol.
final class ViewPreferences : BindableObject {
let didChange = PassthroughSubject<ViewPreferences, Never>()
var showThePasscode: Bool = false {
didSet {
didChange.send(self)
}
}
}
struct PasscodeViewer : View {
@EnvironmentObject var viewPreferences: ViewPreferences
// This is an @EnvironmentObject. It is a reference to a binding which is
// provided by an ancestor view using .environmentObject, and originates
// from outside of the view hierarchy. You can write to the value, and
// whenever it is updated by any source, SwiftUI updates all of the views
// that use it accordingly.
var body: some View {
VStack {
if viewPreferences.showThePasscode {
Text("Hello World!")
}
else {
Text("**********")
}
// We can pass a binding to our @EnvironmentObject with
// the $ prefix. Then, the Toggle component writes to
// the showThePasscode value, which causes all of the
// views that depend on the value to be re-rendered
// by SwiftUI.
Toggle(isOn: $viewPreferences.showThePasscode) {
Text("Show the passcode")
}
// We can also have custom subviews with access to the same
// @EnvironmentObject, without having to pass anything along.
SomeSubView()
}
}
}
struct SomeSubView : View {
@EnvironmentObject var viewPreferences: ViewPreferences
var body: some View {
Group {
if viewPreferences.showThePasscode {
Text("Showing passcodes")
}
else {
Text("Obfuscating passcodes")
}
}
}
}
#if DEBUG
struct PasscodeViewer_Previews : PreviewProvider {
static var previews: some View {
let viewPreferences = ViewPreferences()
return PasscodeViewer()
.environmentObject(viewPreferences)
// With an @EnvironmentObject, we provide the object on one ancestor
// view, giving all of the views in its subview hierarchy access to it.
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment