| name | swift-patterns-advanced |
| description | Advanced Swift patterns — property wrappers, result builders, Combine basics, opaque & existential types, macro system, advanced generics, and performance optimization. Extends swift-patterns. |
Swift Patterns — Advanced
This skill extends swift-patterns with property wrappers, result builders, Combine, macros, and advanced type system features.
When to Activate
- Building custom property wrappers for reusable cross-cutting concerns
- Using result builders for DSLs (like SwiftUI's ViewBuilder)
- Setting up Combine pipelines for reactive data flow
- Optimizing performance with inlining and value type semantics
- Implementing copy-on-write semantics for value types with large internal storage
- Using Swift macros (
@Model, @Observable, #UUID) or writing a custom freestanding macro
- Migrating from
ObservableObject/@Published to the @Observable macro in a SwiftUI app
Property Wrappers
Encapsulate storage and access patterns for properties:
@propertyWrapper
struct Clamped<Value: Comparable> {
var wrappedValue: Value {
didSet { wrappedValue = min(max(wrappedValue, minimum), maximum) }
}
let minimum: Value
let maximum: Value
init(wrappedValue: Value, _ range: ClosedRange<Value>) {
self.minimum = range.lowerBound
self.maximum = range.upperBound
self.wrappedValue = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
}
struct Player {
@Clamped(0...100) var health: Int = 100
@Clamped(0...10) var level: Int = 1
}
var player = Player()
player.health = 150
player.health = -5
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue }
set { UserDefaults.standard.set(newValue, forKey: key) }
}
}
struct Settings {
@UserDefault(key: "theme", defaultValue: "system")
var theme: String
@UserDefault(key: "notifications_enabled", defaultValue: true)
var notificationsEnabled: Bool
}
projectedValue (the $ syntax)
@propertyWrapper
struct Validated<T> {
private(set) var projectedValue: Bool = false
var wrappedValue: T {
didSet { validate() }
}
private let validator: (T) -> Bool
init(wrappedValue: T, _ validator: @escaping (T) -> Bool) {
self.wrappedValue = wrappedValue
self.validator = validator
validate()
}
private mutating func validate() {
projectedValue = validator(wrappedValue)
}
}
struct Form {
@Validated({ !$0.isEmpty && $0.contains("@") })
var email: String = ""
}
var form = Form()
form.email = "alice@example.com"
print(form.$email)
Result Builders
Build DSLs with Swift's @resultBuilder:
@resultBuilder
struct HTMLBuilder {
static func buildBlock(_ components: String...) -> String {
components.joined(separator: "\n")
}
static func buildOptional(_ component: String?) -> String {
component ?? ""
}
static func buildEither(first component: String) -> String { component }
static func buildEither(second component: String) -> String { component }
static func buildArray(_ components: [String]) -> String {
components.joined(separator: "\n")
}
}
func div(@HTMLBuilder content: () -> String) -> String {
"<div>\n\(content())\n</div>"
}
( : ) -> { }
html div {
p()
p()
showFooter {
p()
}
}
Combine Basics
Combine is Apple's reactive framework for processing asynchronous events over time:
import Combine
let cancellable = URLSession.shared
.dataTaskPublisher(for: url)
.map(\.data)
.decode(type: [User].self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { completion in
if case .failure(let error) = completion {
print("Error: \(error)")
}
},
receiveValue: { users in
self.users = users
}
)
let subject = PassthroughSubject<String, Never>()
subject.send("hello")
subject.send(completion: .finished)
let currentValue = CurrentValueSubject<Int, Never>(0)
currentValue.value = 42
let processed = publisher
.filter { $0 > 0 }
.map { $0 * 2 }
.debounce(for: .milliseconds(300), scheduler: RunLoop.main)
.removeDuplicates()
.eraseToAnyPublisher()
combined .(namePublisher, emailPublisher)
.map { name, email }
Opaque Types vs Existentials
Swift 5.7+ has clear semantics for some and any:
protocol Shape {
func area() -> Double
}
func makeCircle(radius: Double) -> some Shape {
Circle(radius: radius)
}
func largestShape(from shapes: [any Shape]) -> (any Shape)? {
shapes.max(by: { $0.area() < $1.area() })
}
protocol Collection<Element> {
associatedtype Element
}
func printAll(_ collection: some Collection<String>) { ... }
func findFirst(_ collection: any Collection<String>, where pred: (String) -> Bool) -> ? { }
Advanced Generics
extension Array: Equatable where Element: Equatable {
static func == (lhs: Array, rhs: Array) -> Bool {
guard lhs.count == rhs.count else { return false }
return zip(lhs, rhs).allSatisfy(==)
}
}
extension Dictionary {
subscript<T>(key: Key, as type: T.Type) -> T? {
self[key] as? T
}
}
struct AnyRepository<Entity, ID>: Repository {
private let _findById: (ID) async throws -> Entity?
private let _save: (Entity) ->
<: >( : ) . , . {
_findById repo.findById
_save repo.save
}
( : ) -> ? { _findById(id) }
( : ) -> { _save(entity) }
}
Swift Macros (Swift 5.9+)
@Model
class User {
var name: String
var email: String
var createdAt: Date
}
let id = #UUID()
#warning("Fix this before shipping")
#error("This platform is not supported")
let file = #fileID
let line = #line
@Observable
class ViewModel {
var users: [User] = []
var isLoading = false
}
Performance Optimization
Avoid Unnecessary Heap Allocations
struct Point { var x, y: Double }
class PointRef { var x, y: Double = 0 }
struct LargeData {
private class Storage {
var data: [UInt8]
init(_ data: [UInt8]) { self.data = data }
}
private var storage: Storage
mutating func append(_ byte: UInt8) {
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(storage.data)
}
storage.data.append(byte)
}
}
@inline and @inlinable
@inlinable
public func clamp<T: Comparable>(_ value: T, to range: ClosedRange<T>) -> T {
min(max(value, range.lowerBound), range.upperBound)
}
@inline(__always)
func fastAdd(_ a: Int, _ b: Int) -> Int { a + b }
Reduce Existential Overhead
func slow(items: [any Drawable]) {
items.forEach { $0.draw() }
}
func fast<D: Drawable>(items: [D]) {
items.forEach { $0.draw() }
}
Concurrency Integration
See swift-concurrency-6-2 for full async/await and Actor patterns.
func fetchAll(ids: [UUID]) async throws -> [User] {
try await withThrowingTaskGroup(of: User.self) { group in
for id in ids {
group.addTask { try await fetchUser(id: id) }
}
return try await group.reduce(into: []) { $0.append($1) }
}
}
struct UserDTO: Sendable {
let id: UUID
let name: String
}
Quick Reference
| Feature | Usage |
|---|
@propertyWrapper | Reusable storage logic (clamping, persistence, validation) |
projectedValue | The $property accessor on property wrappers |
@resultBuilder | DSL syntax (ViewBuilder, custom builders) |
some T | Opaque type — static dispatch, hides concrete type |
any T | Existential — runtime type erasure, heterogeneous |
@Observable | SwiftUI observation (replaces @Published/ObservableObject) |
#UUID() | Freestanding expression macro |
@inlinable | Cross-module inlining for performance-critical code |
isKnownUniquelyReferenced | Implement copy-on-write in value types |
withThrowingTaskGroup | Structured concurrency for parallel async work |