AppCodableStorage - Extends `@AppStorage` in SwiftUI to support any Codable object

Overview

AppCodableStorage

Extends @AppStorage in SwiftUI to support any Codable object. I use SwiftUI for quick prototypes, and this makes it a lot easier to stay organized.

Just swap @AppCodableStorage for @AppStorage and tag your type as PropertyListRepresentable and you're good to go.

Like AppStorage

struct Config: PropertyListRepresentable {
    var username: String
    var profileColor: NSColor?
}

struct MyView: View {

  @AppCodableStorage("user") var settings = Config(username: "Steve")
    
  var body: some View {
    TextField($config.username)
    ...
  }
}

Supported

  • Use storage in multiple views, they automatically reflect the most recent value
  • projectedValue / Bindings so you can pass a sub-object into a sub-view mutably
  • Observes UserDefaults so it can interoperate with other code / defaults write … changes

Outside of SwiftUI

The underlying implementation is in DefaultsWriter, which is useful if you have other subsystems in your app that want to write to and observe UserDefaults in this way. For that purpose, there is also a DefaultsWriter.objectDidChange Publisher to use when you want the updated value rather than a signal that it's about to change.

Limitations

  • Root must code as a Dictionary
  • Encodes to Data and back

The default implementation of PlistReprestable is inelegant, but supports the same use cases as PlistEncoder, since I use PlistEncoder to first convert to Data and then decode the data.

A "better" solution would be to copy-paste most of the code from PlistEncoder to be able to use PlistCoder.encodeToTopLevelContainer(), which is marked internal in the standard library. If it were made public, this could be much more elegant.

Alternates considered

You can use RawRepresentable with the built-in AppStorage to store Codable in a string key in UserDefaults`. This means that your defaults is now unreadable since there is a weird string or binary data in there.

I realize Mike Ash independently made TSUD, which does something pretty similar prior to SwiftUI.

Warning

Do not use this to store a large amount of data! No images, unlimited amounts of text, files etc.

You should sanitize any user input to make sure that it ends up a reasonable size.

You might also like...
A Swift wrapper for system shell over posix_spawn with search path and env support.

AuxiliaryExecute A Swift wrapper for system shell over posix_spawn with search path and env support. Usage import AuxiliaryExecute AuxiliaryExecute.l

Enables developers to write code that interacts with CloudKit in targets that don't support the CloudKit Framework directly

CloudKit Web Services This package enables developers to write code that interac

Enables developers to write code that interacts with CloudKit in targets that don't support the CloudKit Framework directly

CloudKit Web Services This package enables developers to write code that interac

URL query encoder with OpenAPI serialization options support

URLQueryEncoder A customizable Swift Encoder that encodes instances of data type

This SwiftUI project is a result of the second 'milestone' in "Hacking With Swift's 100 Days of SwiftUI".

mutiplication-tables This SwiftUI project is a result of the second 'milestone' in "Hacking With Swift's 100 Days of SwiftUI". In this simple multipli

A property wrapper for displaying up-to-date database content in SwiftUI views

@Query Latest release: November 25, 2021 • version 0.1.0 • CHANGELOG Requirements: iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ • Swift 5.5+ /

A demo app to showcase pixel perfect, modern iOS development with SwiftUI and Combine on MVVM-C architecture.

Pixel_Perfect_SwiftUI A demo app to showcase pixel perfect, modern iOS development with SwiftUI and Combine on MVVM-C architecture. Tech Stack: Swift,

Creating a Todo app using Realm and SwiftUI
Creating a Todo app using Realm and SwiftUI

Realmで作るTodoアプリ note記事「【SwiftUI】Realmを使ってTodoアプリを作る」のソースです。

🇨🇳 Learn how to make WeChat with SwiftUI. 微信 7.0 🟢
🇨🇳 Learn how to make WeChat with SwiftUI. 微信 7.0 🟢

Overview Features Screenshots TODO Requirements License 中文 Overview I will continue to follow the development of technology, the goal is to bring Swif

Comments
  • @MainActor on property wrapper makes compiler unhappy

    @MainActor on property wrapper makes compiler unhappy

    I get this error compiling on more recent toolchains

    Expression requiring global actor 'MainActor' cannot appear in default-value expression of property '_value'; this is an error in Swift 6

    I don't see how to resolve this… internal to AppCodableStorage.init() it wants to grab the correct DefaultsWriter, which is protected by being annotated @MainActor, so this would have to cascade throughout the system and it would be back to implicit queue affinity rather than using actor isolation.

    opened by darknoon 0
Owner
Andrew Pouliot
I work on projects around gpu-accelerated graphics and AI / machine learning. Recently, I worked as an engineer @ lobe.ai, and Design Tools @ Facebook
Andrew Pouliot
A type-safe, protocol-based, pure Swift database offering effortless persistence of any object

There are many libraries out there that aims to help developers easily create and use SQLite databases. Unfortunately developers still have to get bogged down in simple tasks such as writing table definitions and SQL queries. SwiftyDB automatically handles everything you don't want to spend your time doing.

Øyvind Grimnes 489 Sep 9, 2022
Modern interface to UserDefaults + Codable support

Default Modern interface to UserDefaults + Codable support What is Default? Default is a library that extends what UserDefaults can do by providing ex

Nicholas Maccharoli 475 Dec 20, 2022
Store and retrieve Codable objects to various persistence layers, in a couple lines of code!

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve Codable objects t

null 149 Dec 15, 2022
Why not use UserDefaults to store Codable objects 😉

tl;dr You love Swift's Codable protocol and use it everywhere, who doesn't! Here is an easy and very light way to store and retrieve -reasonable amoun

Omar Albeik 452 Oct 17, 2022
CodableFiles - Save and load Codable objects from DocumentDirectory on iOS Devices.

Welcome to CodableFiles, a simple library that provides an easier way to save, load or delete Codable objects in Documents directory. It’s primarily a

Egzon Pllana 36 Dec 20, 2022
CodableCloudKit allows you to easily save and retrieve Codable objects to iCloud Database (CloudKit)

CodableCloudKit CodableCloudKit allows you to easily save and retrieve Codable objects to iCloud Database (CloudKit) Features ℹ️ Add CodableCloudKit f

Laurent Grondin 65 Oct 23, 2022
MoreCodable expands the possibilities of `Codable`.

MoreCodable MoreCodable expands the possibilities of "Codable". Installation Carthage github "tattn/MoreCodable" CocoaPods pod 'MoreCodable' Feature D

Tatsuya Tanaka 372 Dec 7, 2022
Typed key-value storage solution to store Codable types in various persistence layers with few lines of code!

?? Stores A typed key-value storage solution to store Codable types in various persistence layers like User Defaults, File System, Core Data, Keychain

Omar Albeik 94 Dec 31, 2022
CRUD is an object-relational mapping (ORM) system for Swift 4+.

CRUD is an object-relational mapping (ORM) system for Swift 4+. CRUD takes Swift 4 Codable types and maps them to SQL database tables. CRUD can create tables based on Codable types and perform inserts and updates of objects in those tables. CRUD can also perform selects and joins of tables, all in a type-safe manner.

PerfectlySoft Inc. 61 Nov 18, 2022
A Generic CoreData Manager to accept any type of objects. Fastest way for adding a Database to your project.

QuickDB FileManager + CoreData ❗️ Save and Retrieve any thing in JUST ONE line of code ❗️ Fast usage dataBase to avoid struggling with dataBase comple

Behrad Kazemi 17 Sep 24, 2022