Skip to content

Instantly share code, notes, and snippets.

@erdemildiz
Created September 1, 2025 09:32
Show Gist options
  • Save erdemildiz/2886a496aaf7d4eb5840d5ecb9030947 to your computer and use it in GitHub Desktop.
Save erdemildiz/2886a496aaf7d4eb5840d5ecb9030947 to your computer and use it in GitHub Desktop.
Propery Wrapper with Optional Value Support
// Source: https://www.avanderlee.com/swift/property-wrappers/
@propertyWrapper
struct UserDefault<Value> {
let key: String
let defaultValue: Value
var container: UserDefaults = .standard
var wrappedValue: Value {
get {
return container.object(forKey: key) as? Value ?? defaultValue
}
set {
// Check whether we're dealing with an optional and remove the object if the new value is nil.
if let optional = newValue as? AnyOptional, optional.isNil {
container.removeObject(forKey: key)
} else {
container.set(newValue, forKey: key)
}
}
}
var projectedValue: Bool {
return true
}
}
/// Allows to match for optionals with generics that are defined as non-optional.
public protocol AnyOptional {
/// Returns `true` if `nil`, otherwise `false`.
var isNil: Bool { get }
}
extension Optional: AnyOptional {
public var isNil: Bool { self == nil }
}
extension UserDefault where Value: ExpressibleByNilLiteral {
/// Creates a new User Defaults property wrapper for the given key.
/// - Parameters:
/// - key: The key to use with the user defaults store.
init(key: String, _ container: UserDefaults = .standard) {
self.init(key: key, defaultValue: nil, container: container)
}
}
@erdemildiz
Copy link
Author

Example Usage

extension UserDefaults {

    @UserDefault(key: "year_of_birth")
    static var yearOfBirth: Int?
}

UserDefaults.yearOfBirth = 1990
print(UserDefaults.yearOfBirth) // Prints: 1990
UserDefaults.yearOfBirth = nil
print(UserDefaults.yearOfBirth) // Prints: nil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment