SwiftUI: Sharing AppStorage across the whole app
Sharing @AppStorage
without having to pass it into every feature of the app is simply done in the same way it’s done for anything else you want to share: EnvironmentKey. It lets you share a source of truth into a View
hierarchy without needing to pass it into every View
. Use it with @AppStorage
as follows:
import SwiftUI
extension EnvironmentValues {
// if you only need read access
var storageTestMyCustomValue: Bool {
get { self[StorageTest.MyEnvironmentKey.self] }
set { self[StorageTest.MyEnvironmentKey.self] = newValue }
}
// if you need read/write
var storageTestMyCustomValueBinding: Binding<Bool> {
get { self[StorageTest.MyEnvironmentKeyBinding.self] }
set { self[StorageTest.MyEnvironmentKeyBinding.self] = newValue }
}
}
struct StorageTest {
struct MyEnvironmentKey: EnvironmentKey {
static let defaultValue = false
}
struct MyEnvironmentKeyBinding: EnvironmentKey {
static let defaultValue: Binding<Bool> = Binding<Bool>.constant(false)
}
struct ContentView: View {
@AppStorage("StorageTest.Toggle") var isOn = false
var body: some View {
NavigationStack {
List {
AppStorageNotNeededView()
}
}
.environment(\.storageTestMyCustomValueBinding, $isOn)
}
}
struct AppStorageNotNeededView: View {
var body: some View {
AppStorageNeededView()
}
}
struct AppStorageNeededView: View {
@Environment(\.storageTestMyCustomValueBinding) var isOn: Binding<Bool>
var body: some View {
Toggle("Toggle", isOn: isOn.animation())
if isOn.wrappedValue == true {
Text("Row")
}
}
}
}