Skip to content

Instantly share code, notes, and snippets.

@ericlewis
Last active February 17, 2022 16:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericlewis/f664e6183c64c19db5e7f7df2559fe4d to your computer and use it in GitHub Desktop.
Save ericlewis/f664e6183c64c19db5e7f7df2559fe4d to your computer and use it in GitHub Desktop.
All the speed of State with all the benefits of App/SceneStorage!
import SwiftUI
// MARK: Demo
struct ContentView: View {
@State
private var isActive = false
@SceneStorage("OtherKey")
private var isActiveStock = false
var body: some View {
NavigationView {
List {
NavigationLink(destination: ListView(), isActive: $isActive) {
Text("Pushes + Pops Correctly")
}
NavigationLink(destination: ListView(), isActive: $isActiveStock) {
Text("Pushes + Pops Slowly")
}
}
.appStorage($isActive, key: "SomeKey")
}
}
}
struct ListView: View {
var body: some View {
List {
Text("Item")
}
}
}
// MARK: Implementation
struct AppStorageModifier<Value: Equatable>: ViewModifier {
@AppStorage
private var storage: Value
@Binding
private var connection: Value
func body(content: Content) -> some View {
content
.onChange(of: connection) {
storage = $0
}
.onAppear {
connection = storage
}
}
}
extension AppStorageModifier {
init(_ key: String, connecting: Binding<Value>) where Value == Bool {
self._storage = .init(wrappedValue: connecting.wrappedValue, key)
self._connection = connecting
}
init(_ key: String, connecting: Binding<Value>) where Value == Data {
self._storage = .init(wrappedValue: connecting.wrappedValue, key)
self._connection = connecting
}
}
extension View {
func appStorage(_ state: Binding<Bool>, key: String) -> some View {
modifier(AppStorageModifier(key, connecting: state))
}
func appStorage(_ state: Binding<Data>, key: String) -> some View {
modifier(AppStorageModifier(key, connecting: state))
}
}
struct SceneStorageModifier<Value: Equatable>: ViewModifier {
@SceneStorage
private var storage: Value
@Binding
private var connection: Value
func body(content: Content) -> some View {
content
.onChange(of: connection) {
storage = $0
}
.onAppear {
connection = storage
}
}
}
extension SceneStorageModifier {
init(_ key: String, connecting: Binding<Value>) where Value == Bool {
self._storage = .init(wrappedValue: connecting.wrappedValue, key)
self._connection = connecting
}
init(_ key: String, connecting: Binding<Value>) where Value == Data {
self._storage = .init(wrappedValue: connecting.wrappedValue, key)
self._connection = connecting
}
}
extension View {
func sceneStorage(_ state: Binding<Bool>, key: String) -> some View {
modifier(SceneStorageModifier(key, connecting: state))
}
func sceneStorage(_ state: Binding<Data>, key: String) -> some View {
modifier(SceneStorageModifier(key, connecting: state))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment