Skill v1.0.1
currentAutomated scan100/100+4 new
name: swift description: "Language-specific super-code guidelines for swift." risk: safe source: community date_added: "2026-06-16" metadata: version: "1.0.1"
Swift: Idiomatic Efficiency Reference
Apply only within the requested scope and current project conventions. Preserve behavior, ownership, error handling, accessibility and security; examples are independent fragments, not equivalent rewrites in every context. Verify language/library versions and run relevant checks. Required tests and user-facing progress/results take precedence over brevity rules. Do not install dependencies or delete files merely to follow these examples.
When to Use
- Use this skill when the task matches this description: Language-specific super-code guidelines for swift.
Table of Contents
- Optionals
- Collections & Functional Transforms
- Value vs Reference Types
- Error Handling
- Concurrency
- Protocol-Oriented Design
- Anti-patterns specific to Swift
1. Optionals {#optionals}
// ❌ Force unwraplet name = user.name!// ✅ — guard or if-letguard let name = user.name else { return }
// ❌ Nested if-let pyramidif let user = fetchUser() {if let address = user.address {if let city = address.city {display(city)}}}// ✅ — chained optional bindingif let city = fetchUser()?.address?.city {display(city)}// or guard-let for early exitguard let city = fetchUser()?.address?.city else { return }display(city)
// ❌ Ternary for defaultlet name = user.name != nil ? user.name! : "Unknown"// ✅let name = user.name ?? "Unknown"
// ❌ Optional map when if-let is clearer for side effectsuser.name.map { display($0) }// ✅ — map for transforms, if-let for side effectslet upper = user.name.map { $0.uppercased() }if let name = user.name { display(name) }
2. Collections & Functional Transforms {#collections}
// ❌ Imperative filter + mapvar result: [String] = []for item in items {if item.isActive { result.append(item.name.uppercased()) }}// ✅let result = items.filter(\.isActive).map { $0.name.uppercased() }
// ❌ Manual dictionary constructionvar dict: [String: User] = [:]for user in users { dict[user.id] = user }// ✅let dict = Dictionary(users.map { ($0.id, $0) }, uniquingKeysWith: { _, latest in latest }) // same last-write behavior// or with possible duplicates:let dict = Dictionary(grouping: users, by: \.department)
// ❌ Checking isEmpty then accessing firstif !items.isEmpty { process(items[0]) }// ✅if let first = items.first { process(first) }
// ❌ Index-based loopfor i in 0..<items.count { process(items[i]) }// ✅for item in items { process(item) }// with index:for (i, item) in items.enumerated() { process(i, item) }
Use key paths (`\.isActive`) as closure shorthand where supported.
3. Value vs Reference Types {#value-types}
// ❌ Class for plain data (reference semantics where value semantics suffice)class Point {var x: Doublevar y: Doubleinit(x: Double, y: Double) { self.x = x; self.y = y }}// ✅struct Point { var x, y: Double }
// ❌ Large struct copied repeatedly (performance hit)struct HugeData { var buffer: [UInt8] /* thousands of elements */ }func process(_ data: HugeData) { ... } // Array is copy-on-write; read-only passing need not copy the buffer// ✅ — use class or pass inout for mutationfunc process(_ data: inout HugeData) { ... }// or use copy-on-write wrapper for large value types
Default to `struct`. Use `class` when you need identity, inheritance, or reference semantics.
4. Error Handling {#errors}
// ❌ Using optionals to mask errorsfunc parse(_ input: String) -> Data? { ... } // caller doesn't know why it failed// ✅func parse(_ input: String) throws -> Data { ... }
// ❌ try! in production codelet data = try! JSONDecoder().decode(User.self, from: jsonData)// ✅do {let data = try JSONDecoder().decode(User.self, from: jsonData)} catch {logger.error("decode failed: \(error)")throw AppError.decodingFailed(underlying: error)}
// ❌ Generic Error typeenum AppError: Error { case generic(String) }// ✅ — specific, actionable error casesenum AppError: Error {case networkUnreachablecase invalidInput(field: String, reason: String)case unauthorized}
// ❌ Catching all errors and ignoringdo { try riskyOperation() } catch { }// ✅do {try riskyOperation()} catch let error as NetworkError {handleNetworkError(error)} catch {throw error // rethrow unknown}
5. Concurrency {#concurrency}
// ❌ Callback-based async (pyramid of doom)fetchUser { user infetchPosts(for: user) { posts infetchComments(for: posts.first!) { comments indisplay(comments)}}}// ✅ (Swift 5.5+)let user = try await fetchUser()let posts = try await fetchPosts(for: user)guard let firstPost = posts.first else { return }let comments = try await fetchComments(for: firstPost)display(comments)
// ❌ Sequential awaits for independent worklet a = try await fetchA()let b = try await fetchB()// ✅async let a = fetchA()async let b = fetchB()let (resultA, resultB) = try await (a, b)
// ❌ DispatchQueue.main.async for UI updates in async contextDispatchQueue.main.async { label.text = result }// ✅await MainActor.run { label.text = result }// or mark the function/class @MainActor
Use `actor` for mutable shared state instead of manual locks/queues.
6. Protocol-Oriented Design {#protocols}
// ❌ Deep class inheritance hierarchyclass Animal { ... }class Dog: Animal { ... }class GuideDog: Dog { ... }// ✅ — protocols + compositionprotocol Animal { var name: String { get } }protocol Trainable { func train() }struct Dog: Animal, Trainable { ... }
// ❌ Protocol with default implementations for everythingprotocol Renderable {func render()}extension Renderable {func render() { /* default */ }}// Every conformer uses default — protocol serves no purpose// ✅ — only default implementations that provide genuine shared logic
// ❌ Associated type when generic parameter sufficesprotocol Container {associatedtype Elementfunc get() -> Element}// ✅ — use `some` or generic parameter for simple casesfunc process(_ item: some Equatable) { ... }
7. Anti-patterns specific to Swift {#antipatterns}
| Anti-pattern | Preferred | |
|---|---|---|
Force unwrap ! in production code | guard let / if let / ?? | |
try! outside tests | do/catch | |
class for plain data | struct | |
| Deep inheritance hierarchies | protocol composition | |
@objc when pure Swift works | native Swift types | |
NSArray / NSDictionary | Array / Dictionary | |
DispatchQueue in async/await code | actor / MainActor | |
| Implicitly unwrapped optionals as fields | regular optionals or non-optional with init | |
Any / AnyObject everywhere | generics with protocol constraints | |
Massive switch over string values | enum with raw values | |
| Singleton pattern (global mutable state) | dependency injection |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.