| name | swift |
| description | Language-specific super-code guidelines for swift. |
| risk | safe |
| source | community |
| date_added | 2026-06-16 |
Swift: Idiomatic Efficiency Reference
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}
let name = user.name!
guard let name = user.name else { return }
if let user = fetchUser() {
if let address = user.address {
if let city = address.city {
display(city)
}
}
}
if let city = fetchUser()?.address?.city {
display(city)
}
guard let city = fetchUser()?.address?.city else { return }
display(city)
let name = user.name != nil ? user.name! : "Unknown"
let name = user.name ?? "Unknown"
user.name.map { display($0) }
let upper = user.name.map { $0.uppercased() }
if let name = user.name { display(name) }
2. Collections & Functional Transforms {#collections}
var result: [String] = []
for item in items {
if item.isActive { result.append(item.name.uppercased()) }
}
let result = items
.filter(\.isActive)
.map { $0.name.uppercased() }
var dict: [String: User] = [:]
for user in users { dict[user.id] = user }
let dict = Dictionary(uniqueKeysWithValues: users.map { ($0.id, $0) })
let dict = Dictionary(grouping: users, by: \.department)
if !items.isEmpty { process(items[0]) }
if let first = items.first { process(first) }
for i in 0..<items.count { process(items[i]) }
for item in items { process(item) }
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 Point {
var x: Double
var y: Double
init(x: Double, y: Double) { self.x = x; self.y = y }
}
struct Point { var x, y: Double }
struct HugeData { var buffer: [UInt8] }
func process(_ data: HugeData) { ... }
func process(_ data: inout HugeData) { ... }
Default to struct. Use class when you need identity, inheritance, or reference semantics.
4. Error Handling {#errors}
func parse(_ input: String) -> Data? { ... }
func parse(_ input: String) throws -> Data { ... }
let 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)
}
enum AppError: Error { case generic(String) }
enum AppError: Error {
case networkUnreachable
case invalidInput(field: String, reason: String)
case unauthorized
}
do { try riskyOperation() } catch { }
do {
try riskyOperation()
} catch let error as NetworkError {
handleNetworkError(error)
} catch {
throw error
}
5. Concurrency {#concurrency}
fetchUser { user in
fetchPosts(for: user) { posts in
fetchComments(for: posts.first!) { comments in
display(comments)
}
}
}
let user = try await fetchUser()
let posts = try await fetchPosts(for: user)
let comments = try await fetchComments(for: posts[0])
display(comments)
let 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 { label.text = result }
await MainActor.run { label.text = result }
Use actor for mutable shared state instead of manual locks/queues.
6. Protocol-Oriented Design {#protocols}
class Animal { ... }
class Dog: Animal { ... }
class GuideDog: Dog { ... }
protocol Animal { var name: String { get } }
protocol Trainable { func train() }
struct Dog: Animal, Trainable { ... }
protocol Renderable {
func render()
}
extension Renderable {
func render() { }
}
protocol Container {
associatedtype Element
func get() -> Element
}
func 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.