fix: Reuse JSONEncoder and JSONDecoder instances in TypedAppStorage

This commit is contained in:
Shibo Lyu 2025-06-14 20:01:02 +08:00
parent 27d4026050
commit b3326032f6

View file

@ -18,13 +18,15 @@ public protocol TypedAppStorageValue: Codable, Sendable {
public struct TypedAppStorage<Value: TypedAppStorageValue>: DynamicProperty {
private var appStorage: AppStorage<String>
private var initialValue: Value
private let encoder = JSONEncoder()
private let decoder = JSONDecoder()
/// Store and fetch value from the defined store, with a predefined default value.
///
/// This default value if defined is preferred over ``TypedAppStorageValue/defaultValue``.
public init(wrappedValue: Value, store: UserDefaults? = nil) {
initialValue = wrappedValue
let initialData = try? JSONEncoder().encode(wrappedValue)
let initialData = try? encoder.encode(wrappedValue)
let initialString =
(initialData == nil ? nil : String(data: initialData!, encoding: .utf8))
?? ""
@ -48,11 +50,11 @@ public struct TypedAppStorage<Value: TypedAppStorageValue>: DynamicProperty {
guard let data = appStorage.wrappedValue.data(using: .utf8) else {
return initialValue
}
return (try? JSONDecoder().decode(Value.self, from: data)) ?? initialValue
return (try? decoder.decode(Value.self, from: data)) ?? initialValue
}
nonmutating set {
guard
let newData = try? JSONEncoder().encode(newValue),
let newData = try? encoder.encode(newValue),
let newString = String(data: newData, encoding: .utf8)
else { return }
appStorage.wrappedValue = newString