Last active
June 11, 2019 14:23
-
-
Save alexobenauer/8ba0182cf36b7f4025a9b34fa003086c to your computer and use it in GitHub Desktop.
How EnvironmentObjects work in SwiftUI views
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
// | |
// 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