guillermomuntaner
Burritos
Swift

A collection of Swift Property Wrappers (formerly "Property Delegates")

Last updated Jun 30, 2026
1.3k
Stars
43
Forks
10
Issues
0
Stars/day
Attention Score
62
Language breakdown
No language data available.
โ–ธ Files click to expand
README

๐ŸŒฏ๐ŸŒฏ Burritos

Bitrise Build Status Swift Package Manager Platform

A collection of well tested Swift Property Wrappers.

Requirements

Xcode 11 & Swift 5

Installation

Swift Package Manager

Xcode 11+ integration

  • Open MenuBar โ†’ File โ†’ Swift Packages โ†’ Add Package Dependency...
  • Paste the package repository url https://github.com/guillermomuntaner/Burritos and hit Next.
  • Select your rules. Since this package is in pre-release development, I suggest you specify a concrete tag to avoid pulling breaking changes.

Package.swift

If you already have a Package.swift or you are building your own package simply add a new dependency:
dependencies: [
    .package(url: "https://github.com/guillermomuntaner/Burritos", from: "0.0.3")
]

Cocoapods

Add Burritos to your Podfile:

pod 'Burritos', '~> 0.0.3'

Each wrapper is a submodule, so you add just the one(s) you want

pod 'Burritos/Copying', '~> 0.0.3' pod 'Burritos/UndoRedo', '~> 0.0.3' pod 'Burritos/UserDefault', '~> 0.0.3'

@AtomicWrite

A property wrapper granting atomic write access to the wrapped property. Reading access is not atomic but is exclusive with write & mutate operations. Atomic mutation (read-modify-write) can be done using the wrapper mutate method.

@Atomic var count = 0

// You can atomically write (non-derived) values directly: count = 99

// To mutate (read-modify-write) always use the wrapper method: DispatchQueue.concurrentPerform(iterations: 1000) { index in _count.mutate { $0 += 1 } }

print(count) // 1099

@Clamping

A property wrapper that automatically clamps its wrapped value in a range.

@Clamping(range: 0...1) var alpha: Double = 0.0

alpha = 2.5 print(alpha) // 1.0

alpha = -1.0 print(alpha) // 0.0

@Copying

A property wrapper arround NSCopying that copies the value both on initialization and reassignment. If you are tired of calling .copy() as! X you will love this one.

@Copying var path: UIBezierPath = .someInitialValue

public func updatePath(_ path: UIBezierPath) { self.path = path // You don't need to worry whoever called this method mutates the passed by reference path. // Your stored self.path contains a copy. }

@DefaultValue

A property wrapper arround an implicitly unwrapped optional value which fallbacks to a given default value.

@DefaultValue(default: 0)
var count
count = 100
// or
@DefaultValue(default: 0)
var count = 100

// Assigning nil resets to the default value print(count) // 100 count = nil print(count) // 0

@DynamicUIColor

A property wrapper arround UIColor to support dark mode.

By default in iOS >= 13 it uses the new system wide user interface style trait and dynamic UIColor constructor to support dark mode without any extra effort. On prior iOS versions it defaults to light.

@DynamicUIColor(light: .white, dark: .black) var backgroundColor: UIColor

// The color will automatically update when traits change view.backgroundColor = backgroundColor

To support older iOS versions and custom logics (e.g. a switch in your app settings) the constructor can take an extra style closure that dynamically dictates which color to use. Returning a nil value results in the prior default behaviour. This logic allows easier backwards compatiblity by doing:

let color = DynamicUIColor(light: .white, dark: .black) {
    if #available(iOS 13.0, *) { return nil }
    else { return Settings.isDarkMode ? .dark : .light }
}

view.backgroundColor = color.value

// On iOS <13 you might need to manually observe your custom dark // mode settings & re-bind your colors on changes: if #available(iOS 13.0, *) {} else { Settings.onDarkModeChange { [weak self] in self?.view.backgroundColor = self?.color.value } }

Original idea courtesy of @bardonadam

@EnvironmentVariable

A property wrapper to set and get system environment variables values.

@EnvironmentVariable(name: "PATH")
var path: String?

// You can set the environment variable directly: path = "~/opt/bin:" + path!

@Expirable

A property wrapper arround a value that can expire. Getting the value after given duration or expiration date will return nil.

@Expirable(duration: 60)
var apiToken: String?

// New values will be valid for 60s apiToken = "123456abcd" print(apiToken) // "123456abcd" sleep(61) print(apiToken) // nil

// You can also construct an expirable with an initial value and expiration date: @Expirable(wrappedValue: "zyx987", expirationDate: date, duration: 60) var apiToken: String? // or just update an existing one: _apiToken.set("zyx987", expirationDate: date)

Courtesy of @v_pradeilles

@LateInit

A reimplementation of Swift Implicitly Unwrapped Optional using a property wrapper.

var text: String!
// or 
@LateInit var text: String

// Note: Accessing it before initializing will result in a fatal error: // print(text) // -> fatalError("Trying to access LateInit.value before setting it.")

// Later in your code: text = "Hello, World!"

@Lazy

A property wrapper which delays instantiation until first read access. It is a reimplementation of Swift lazy modifier using a property wrapper.

@Lazy var result = expensiveOperation()
...
print(result) // expensiveOperation() is executed at this point

As an extra on top of lazy it offers reseting the wrapper to its "uninitialized" state.

@LazyConstant

Same as @Lazy + prevents changing or mutating its wrapped value.

@LazyConstant var result = expensiveOperation()
...
print(result) // expensiveOperation() is executed at this point

result = newResult // Compiler error

Note: This wrapper prevents reassigning the wrapped property value but NOT the wrapper itself. Reassigning the wrapper _value = LazyConstant(wrappedValue: "Hola!") is possible and since wrappers themselves need to be declared variable there is no way to prevent it.

@Trimmed

A wrapper that automatically trims strings both on initialization and reassignment.

@Trimmed
var text = " \n Hello, World! \n\n    "

print(text) // "Hello, World!"

// By default trims white spaces and new lines, but it also supports any character set @Trimmed(characterSet: .whitespaces) var text = " \n Hello, World! \n\n " print(text) // "\n Hello, World! \n\n"

@UndoRedo

A property wrapper that automatically stores history and supports undo and redo operations.

@UndoRedo var text = ""

text = "Hello" text = "Hello, World!"

_text.canUndo // true _text.undo() // text == "Hello"

_text.canRedo // true _text.redo() // text == "Hello, World!"

You can check at any time if there is an undo or a redo stack using canUndo & canRedo properties, which might be particularly usefull to enable/disable user interface buttons.

Original idea by @JeffHurray

@UserDefault

Type safe access to UserDefaults with support for default values.

@UserDefault("test", defaultValue: "Hello, World!") var test: String

By default it uses the standard user defauls. You can pass any other instance of UserDefaults you want to use via its constructor, e.g. when you use app groups:

let userDefaults = UserDefaults(suiteName: "your.app.group")
@UserDefault("test", defaultValue: "Hello, World!", userDefaults: userDefaults)
var test: String

@Cached

TODO

@Dependency (Service locator pattern)

TODO

Thread safety

TODO

Command line parameters

TODO

Property observer -> willSet, didSet !

TODO: Reimplement

Print/Log

TODO: A property wrapper that prints/logs any value set.

About Property Wrappers

Quoting the Property Wrappers Proposal description:

A property wrapper is a mechanism to abstract property implementation patterns that come up repeatedly.

๐Ÿ‘‰ Did you know: Property Wrappers were announced by Apple during WWDC 2019. They are a fundamental component in SwiftUI syntax sugar hence Apple pushed them into the initial Swift 5.1 beta, skipping the normal Swift Evolution process. This process continued after WWDC and it took 3 reviews to reach their final form on Xcode 11 beta 4.

Interesting reads:

Equivalents in other languages:

License

Burritos is released under the MIT license.

ยฉ 2026 GitRepoTrend ยท guillermomuntaner/Burritos ยท Updated daily from GitHub