Logging Property Access
@propertyWrapper
struct LogAccess<T> {
private var value: T
private let propertyName: String
init(wrappedValue: T, propertyName: String) {
self.value = wrappedValue
self.propertyName = propertyName
}
var wrappedValue: T {
get {
print("Accessing \(propertyName) with value: \(value)")
return value
}
set {
value = newValue
print("Setting \(propertyName) to \(value)")
}
}
}
struct Example {
@LogAccess(propertyName: "testProperty")
var testProperty: Int
}
Validating Property
@propertyWrapper
struct ValidateRange {
private var value: Int
private let range: ClosedRange<Int>
init(wrappedValue: Int, range: ClosedRange<Int>) {
self.range = range
self.value = wrappedValue.clamped(to: range)
}
var wrappedValue: Int {
get { value }
set { value = newValue.clamped(to: range) }
}
}
struct MySettings {
@ValidateRange(range: 1...10)
var volume: Int
}
Lazy Initialization
@propertyWrapper
struct Lazy<T> {
private var initializer: () -> T
private var _value: T?
init(wrappedValue: @autoclosure @escaping () -> T) {
self.initializer = wrappedValue
}
var wrappedValue: T {
mutating get {
if let value = _value {
return value
} else {
let value = initializer()
_value = value
return value
}
}
}
}
struct MyStruct {
@Lazy var expensiveObject: ExpensiveClass = ExpensiveClass()
}
Thread-Safe Access
@propertyWrapper
struct ThreadSafe<T> {
private var value: T
private let queue = DispatchQueue(label: "ThreadSafeQueue", attributes: .concurrent)
init(wrappedValue: T) {
self.value = wrappedValue
}
var wrappedValue: T {
get {
return queue.sync { value }
}
set {
queue.async(flags: .barrier) { self.value = newValue }
}
}
}
struct SafeData {
@ThreadSafe var data: Int
}
Observing Property Changes
@propertyWrapper
struct DidSet<T> {
private var value: T
private let callback: (T) -> Void
init(wrappedValue: T, _ callback: @escaping (T) -> Void) {
self.value = wrappedValue
self.callback = callback
}
var wrappedValue: T {
get { value }
set {
value = newValue
callback(newValue)
}
}
}
class MyClass {
@DidSet({ print("Value changed to \($0)") }) var myProperty: Int
}
UserDefaults
@propertyWrapper
struct UserDefaultsBacked<Value> {
let key: String
var wrappedValue: Value? {
get { UserDefaults.standard.object(forKey: key) as? Value }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
}
struct Settings {
@UserDefaultsBacked(key: "autoRefresh")
var autoRefresh: Bool?
}