Swiftpack.co -  jessesquires/Foil as Swift Package
Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
A lightweight property wrapper for UserDefaults done right
.package(url: "https://github.com/jessesquires/Foil.git", from: "1.2.0")

Foil Actions Status

A lightweight property wrapper for UserDefaults done right


Read the post: A better approach to writing a UserDefaults Property Wrapper

Why the name?

Foil, as in let me quickly and easily wrap and store this leftover food in some foil so I can eat it later. 🌯 😉

North America
A very thin, pliable, easily torn sheet of aluminum used for cooking, packaging, cosmetics, and insulation.


You can use @WrappedDefault for non-optional values and @WrappedDefaultOptional for optional ones. You may wish to store all your user defaults in one place, however, that is not necessary. Any property on any type can use this wrapper.

final class AppSettings {
    static let shared = AppSettings()

    @WrappedDefault(keyName: "flagEnabled", defaultValue: true)
    var flagEnabled: Bool

    @WrappedDefault(keyName: "totalCount", defaultValue: 0)
    var totalCount: Int

    @WrappedDefaultOptional(keyName: "timestamp")
    var timestamp: Date?

// Usage

func userDidToggleSetting(_ sender: UISwitch) {
    AppSettings.shared.flagEnabled = sender.isOn

There is also an included example app project.

Using enum keys

If you prefer using an enum for the keys, writing an extension specific to your app is easy. However, this is not required. In fact, unless you have a specific reason to reference the keys, this is completely unneccessary.

enum AppSettingsKey: String, CaseIterable {
    case flagEnabled
    case totalCount
    case timestamp

extension WrappedDefault {
    init(key: AppSettingsKey, defaultValue: T) {
        self.init(keyName: key.rawValue, defaultValue: defaultValue)

extension WrappedDefaultOptional {
    init(key: AppSettingsKey) {
        self.init(keyName: key.rawValue)

Observing with Combine

To support KVO monitoring via Combine, use the NSObject.KeyValueObservingPublisher helpers provided by Apple. This requires your object to inherit from NSObject and adding @objc dynamic to the properties you would like to observe:

final class AppSettings: NSObject {
    static let shared = AppSettings()

    @WrappedDefaultOptional(keyName: "nickname")
    @objc dynamic var nickname: String?

// Usage

    .publisher(for: \.nickname, options: [.new])
    .sink { print($0) }
    .store(in: &cancellable)

AppSettings.shared.nickname = "abc123"
// prints "abc123" from `.sink`

Supported types

The following types are supported by default for use with @WrappedDefault.

Adding support for custom types is possible by conforming to UserDefaultsSerializable. However, this is highly discouraged. UserDefaults is not intended for storing complex data structures and object graphs. You should probably be using a proper database (or serializing to disk via Codable) instead.

  • Bool
  • Int
  • UInt
  • Float
  • Double
  • String
  • URL
  • Date
  • Data
  • Array
  • Set
  • Dictionary
  • RawRepresentable types

Additional Resources

Supported Platforms

  • iOS 9.0+
  • tvOS 9.0+
  • watchOS 5.0+
  • macOS 10.13+




pod 'Foil', '~> 1.0.0'

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/jessesquires/Foil.git", from: "1.0.0")

Alternatively, you can add the package directly via Xcode.


You can read the documentation here. Generated with jazzy. Hosted by GitHub Pages.


Interested in making contributions to this project? Please review the guides below.

Also, consider sponsoring this project or buying my apps! ✌️


Created and maintained by Jesse Squires.


Released under the MIT License. See LICENSE for details.

Copyright © 2021-present Jesse Squires.


Stars: 244
Last commit: 3 days ago

Ad: Job Offers

iOS Software Engineer @ Perry Street Software
Perry Street Software is Jack’d and SCRUFF. We are two of the world’s largest gay, bi, trans and queer social dating apps on iOS and Android. Our brands reach more than 20 million members worldwide so members can connect, meet and express themselves on a platform that prioritizes privacy and security. We invest heavily into SwiftUI and using Swift Packages to modularize the codebase.

Release Notes

1.2.0: Leftover Falafel 🧆
8 weeks ago

This release closes the 1.2.0 milestone.

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API