Skip to content

Instantly share code, notes, and snippets.

@zntfdr
Last active August 17, 2020 16:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zntfdr/d0cf1f7ba01613960577ac92ec89c5c5 to your computer and use it in GitHub Desktop.
Save zntfdr/d0cf1f7ba01613960577ac92ec89c5c5 to your computer and use it in GitHub Desktop.
// Original article here: https://www.fivestars.blog/swiftui/app-scene-storage.html
import Combine
import SwiftUI
// MARK: Appearance
enum Appearance: String, Codable, CaseIterable, Identifiable {
case dark
case light
case system
var id: String { rawValue }
}
struct Preferences: Codable {
var appearance: Appearance
static let defaultValue = Preferences(appearance: .system)
}
// MARK: ContentView
class ContentViewModel: ObservableObject {
@Published("userPreferences") var preferences: Preferences = .defaultValue
}
struct ContentView: View {
@StateObject var model = ContentViewModel()
var body: some View {
Picker("Appearance", selection: $model.preferences.appearance) {
ForEach(Appearance.allCases, id: \.self) {
Text(verbatim: $0.rawValue)
}
}.pickerStyle(SegmentedPickerStyle())
}
}
// MARK: Published+UserDefaults
private var cancellableSet: Set<AnyCancellable> = []
extension Published where Value: Codable {
init(wrappedValue defaultValue: Value, _ key: String, store: UserDefaults? = nil) {
let _store: UserDefaults = store ?? .standard
if
let data = _store.data(forKey: key),
let value = try? JSONDecoder().decode(Value.self, from: data) {
self.init(initialValue: value)
} else {
self.init(initialValue: defaultValue)
}
projectedValue
.sink { newValue in
let data = try? JSONEncoder().encode(newValue)
_store.set(data, forKey: key)
}
.store(in: &cancellableSet)
}
}
// MARK: Published+UISceneSession
extension Published where Value: Codable {
init(wrappedValue defaultValue: Value, _ key: String, session: UISceneSession) {
if
let data = session.userInfo?[key] as? Data,
let value = try? JSONDecoder().decode(Value.self, from: data) {
self.init(initialValue: value)
} else {
self.init(initialValue: defaultValue)
}
projectedValue
.sink { newValue in
let data = try? JSONEncoder().encode(newValue)
session.userInfo?[key] = data
}
.store(in: &cancellableSet)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment