Skip to content

Instantly share code, notes, and snippets.

@Jiropole
Created September 4, 2024 18:42
Show Gist options
  • Select an option

  • Save Jiropole/7dc1c0469d0ee52224d2e825dcdffbd0 to your computer and use it in GitHub Desktop.

Select an option

Save Jiropole/7dc1c0469d0ee52224d2e825dcdffbd0 to your computer and use it in GitHub Desktop.
Support using an arbitrary Codable value with AppStorage, with syntactic sugar to avoid referring directly to wrapped value.
//
// AppStorageCodable.swift
//
//
// Created by Jesse Hemingway on 9/4/24.
//
import Foundation
import SwiftUI
/**
Support arbitrary Codable values with AppStorage,
including syntactic sugar to avoid referring directly to wrapped value.
Example usage:
```
struct ExampleStruct: Codable {
var id: Int = 0
var name: String = "John"
}
class ExampleVendor: ObservableObject {
@AppStorage("example")
@AppStorageCodable
var example: ExampleStruct = .init()
}
func testAppStorageCodable() {
let exampleVendor = ExampleVendor()
print("Example id: \(exampleVendor.example.id), name: \(exampleVendor.example.name)")
}
```
*/
@propertyWrapper
@dynamicMemberLookup
public struct AppStorageCodable<Value: Codable> {
public var wrappedValue: Value
public init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
subscript<T>(dynamicMember keyPath: WritableKeyPath<Value, T>) -> T {
get { wrappedValue[keyPath: keyPath] }
set { wrappedValue[keyPath: keyPath] = newValue }
}
}
extension AppStorageCodable: RawRepresentable {
public typealias RawValue = String
public var rawValue: RawValue {
guard let data = try? JSONEncoder().encode(wrappedValue),
let string = String(data: data, encoding: .utf8) else { return "" }
return string
}
public init?(rawValue: RawValue) {
guard let data = rawValue.data(using: .utf8),
let decoded = try? JSONDecoder().decode(Value.self, from: data) else { return nil }
wrappedValue = decoded
}
}
extension AppStorageCodable: Equatable where Value: Equatable {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment