# Swift Coding Standards

Best practices for writing clean, safe, and idiomatic Swift code following Apple's guidelines and modern Swift conventions.

---

## 1. Optionals and Safety

**Impact:** CRITICAL

Swift's optional system eliminates null pointer exceptions through compile-time safety.

### 1.1 Safe Unwrapping with if let

```swift
if let name = optionalName {
    print("Hello, \(name)")
}

// Multiple bindings
if let name = userName, let age = userAge, age >= 18 {
    print("\(name) is an adult")
}
```

### 1.2 Guard for Early Exit

Use `guard` to exit early when preconditions aren't met:

```swift
func processUser(_ user: User?) {
    guard let user = user else { return }
    guard !user.name.isEmpty else { return }
    print(user.name)
}
```

### 1.3 Nil Coalescing for Defaults

```swift
let displayName = name ?? "Anonymous"
let count = items?.count ?? 0
```

### 1.4 Optional Chaining

```swift
let count = user?.profile?.posts?.count
let uppercased = optionalString?.uppercased()
```

### 1.5 Optional map/flatMap

```swift
let uppercasedName = userName.map { $0.uppercased() }
let userID = userIDString.flatMap { Int($0) }
```

### 1.6 Never Force Unwrap

Avoid `!` force unwrapping. Use safe alternatives:

| Instead of | Use |
|------------|-----|
| `value!` | `if let value = value { }` |
| `array[0]` (unsafe) | `array.first` |
| `dictionary["key"]!` | `dictionary["key", default: defaultValue]` |

---

## 2. Naming Conventions

**Impact:** HIGH

### 2.1 Types: PascalCase

```swift
class UserProfileViewController { }
struct NetworkRequest { }
protocol DataSource { }
enum LoadingState { }
```

### 2.2 Variables and Functions: camelCase

```swift
var userName: String
let maximumRetryCount = 3
func fetchUserProfile() { }
```

### 2.3 Boolean Naming

Use `is`, `has`, `should`, `can` prefixes:

```swift
var isLoading: Bool
var hasCompletedOnboarding: Bool
var shouldShowAlert: Bool
var canEditProfile: Bool
```

### 2.4 Function Naming

Use verb phrases, read like natural English:

```swift
// Good - clear actions
func fetchUsers() async throws -> [User]
func remove(_ item: Item, at index: Int)
func makeIterator() -> Iterator

// Avoid - unclear or redundant
func getUsersData() // "get" is redundant
func doRemove() // vague
```

### 2.5 Parameter Labels

First parameter label can be omitted when obvious:

```swift
func insert(_ element: Element, at index: Int)
func move(from source: Int, to destination: Int)
```

---

## 3. Protocol-Oriented Design

**Impact:** HIGH

Swift favors composition over inheritance through protocols.

### 3.1 Define Capabilities Through Protocols

```swift
protocol DataStore {
    func save<T: Codable>(_ item: T, key: String) throws
    func load<T: Codable>(key: String) throws -> T?
}

protocol Drawable {
    var color: Color { get set }
    func draw()
}
```

### 3.2 Protocol Extensions for Default Behavior

```swift
extension Drawable {
    func draw() {
        print("Drawing with \(color)")
    }
}

extension Collection {
    func chunked(into size: Int) -> [[Element]] {
        guard size > 0 else { return [] }

        var result: [[Element]] = []
        var i = startIndex

        while i != endIndex {
            let j = index(i, offsetBy: size, limitedBy: endIndex) ?? endIndex
            result.append(Array(self[i..<j]))
            i = j
        }

        return result
    }
}
```

### 3.3 Associated Types for Flexibility

```swift
protocol Repository {
    associatedtype Item
    func fetchAll() async throws -> [Item]
    func save(_ item: Item) async throws
}

class UserRepository: Repository {
    typealias Item = User
    
    func fetchAll() async throws -> [User] { /* ... */ }
    func save(_ item: User) async throws { /* ... */ }
}
```

### 3.4 Protocol Composition

```swift
protocol Named { var name: String { get } }
protocol Aged { var age: Int { get } }

func greet(_ person: Named & Aged) {
    print("Hello, \(person.name), age \(person.age)")
}
```

---

## 4. Value Types vs Reference Types

**Impact:** HIGH

### 4.1 Prefer Structs (Value Types)

Use structs for simple data models, independent copies:

```swift
struct User {
    var name: String
    var email: String
}

struct Point {
    var x: Double
    var y: Double
}
```

### 4.2 Use Classes When Needed

Use classes when identity, shared ownership, or reference semantics matter.
Prefer actors for mutable state shared across concurrent tasks:

```swift
class NetworkManager {
    static let shared = NetworkManager()
    private init() { }
}

class FileHandle {
    // Wrapping system resource
}
```

### 4.3 Enums for Finite States

```swift
enum LoadingState {
    case idle
    case loading
    case success(Data)
    case failure(Error)
}

enum Result<Success, Failure: Error> {
    case success(Success)
    case failure(Failure)
}
```

| Type | Use When |
|------|----------|
| `struct` | Data models, coordinates, independent values |
| `class` | Shared state, identity matters, inheritance needed |
| `enum` | Finite set of options, state machines |

---

## 5. Memory Management with ARC

**Impact:** CRITICAL

### 5.1 Breaking Retain Cycles with weak

```swift
class Apartment {
    weak var tenant: Person?
}

class Person {
    var apartment: Apartment?
}
```

### 5.2 Closure Capture Lists

Use capture lists intentionally to avoid retain cycles.
Choose `weak` or `unowned` based on lifetime guarantees:

```swift
// Weak capture for optional self
onComplete = { [weak self] in
    self?.processResult()
}

// Capture specific values
let id = user.id
fetchData { [id] result in
    print("Fetched for \(id)")
}
```

### 5.3 unowned for Guaranteed Lifetime

Use when reference should never be nil during object lifetime:

```swift
class CreditCard {
    unowned let customer: Customer
    
    init(customer: Customer) {
        self.customer = customer
    }
}
```

| Keyword | Use When |
|---------|----------|
| `weak` | Reference may become nil |
| `unowned` | Reference guaranteed to outlive |
| None | Strong ownership needed |

---

## 6. Error Handling

**Impact:** HIGH

### 6.1 Define Typed Errors

```swift
enum NetworkError: Error {
    case invalidURL
    case noConnection
    case serverError(statusCode: Int)
    case decodingFailed(underlying: Error)
}

enum ValidationError: LocalizedError {
    case emptyField(name: String)
    case invalidFormat(field: String, expected: String)
    
    var errorDescription: String? {
        switch self {
        case .emptyField(let name):
            return "\(name) cannot be empty"
        case .invalidFormat(let field, let expected):
            return "\(field) must be \(expected)"
        }
    }
}
```

### 6.2 Throwing Functions

```swift
func fetchUser(id: Int) throws -> User {
    guard let url = URL(string: "https://api.example.com/users/\(id)") else {
        throw NetworkError.invalidURL
    }
    // ... implementation
}
```

### 6.3 Do-Catch Handling

```swift
do {
    let user = try fetchUser(id: 123)
    print(user.name)
} catch NetworkError.serverError(let code) {
    print("Server error: \(code)")
} catch NetworkError.noConnection {
    print("Check your internet connection")
} catch {
    print("Unknown error: \(error)")
}
```

### 6.4 try? and try!

```swift
// try? returns optional (nil on error)
let user = try? fetchUser(id: 123)

// try! crashes on error - use only when failure is programmer error
let config = try! loadBundledConfig()
```

### 6.5 Rethrows

```swift
func perform<T>(_ operation: () throws -> T) rethrows -> T {
    return try operation()
}
```

---

## 7. Modern Concurrency (async/await)

**Impact:** CRITICAL

Use actor isolation and `Sendable` to prevent data races across concurrency domains.

### 7.1 Async Functions

```swift
func fetchUser(id: Int) async throws -> User {
    guard let url = URL(string: "https://api.example.com/users/\(id)") else {
        throw NetworkError.invalidURL
    }
    let (data, _) = try await URLSession.shared.data(from: url)
    return try JSONDecoder().decode(User.self, from: data)
}

// Calling async functions
Task {
    do {
        let user = try await fetchUser(id: 123)
        print(user.name)
    } catch {
        print("Failed: \(error)")
    }
}
```

### 7.2 Parallel Execution with TaskGroup

```swift
func fetchAllUsers(ids: [Int]) 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) }
    }
}
```

### 7.3 async let for Concurrent Bindings

```swift
async let user = fetchUser(id: 1)
async let posts = fetchPosts(userId: 1)
async let followers = fetchFollowers(userId: 1)

let profile = try await ProfileData(
    user: user,
    posts: posts,
    followers: followers
)
```

### 7.4 Actors for Thread-Safe State

```swift
actor BankAccount {
    private var balance: Double = 0
    
    func deposit(_ amount: Double) {
        balance += amount
    }
    
    func withdraw(_ amount: Double) throws {
        guard balance >= amount else {
            throw BankError.insufficientFunds
        }
        balance -= amount
    }
    
    func getBalance() -> Double {
        balance
    }
}

// Usage
let account = BankAccount()
await account.deposit(100)
let balance = await account.getBalance()
```

### 7.5 MainActor for UI Updates

```swift
@MainActor
class ViewModel: ObservableObject {
    @Published var isLoading = false
    @Published var users: [User] = []
    
    func loadUsers() async {
        isLoading = true
        defer { isLoading = false }
        
        do {
            users = try await fetchUsers()
        } catch {
            // Handle error
        }
    }
}
```

### 7.6 Task Cancellation

```swift
func fetchWithTimeout() async throws -> Data {
    try await withThrowingTaskGroup(of: Data.self) { group in
        group.addTask {
            try await fetchData()
        }
        group.addTask {
            try await Task.sleep(for: .seconds(10))
            throw TimeoutError()
        }
        
        let result = try await group.next()!
        group.cancelAll()
        return result
    }
}

// Check for cancellation
func longOperation() async throws {
    for item in items {
        try Task.checkCancellation()
        await process(item)
    }
}
```

---

## 8. Access Control

**Impact:** MEDIUM

### 8.1 Access Levels

| Level | Scope |
|-------|-------|
| `private` | Enclosing declaration only |
| `fileprivate` | Entire source file |
| `internal` | Module (default) |
| `public` | Other modules can access |
| `open` | Other modules can subclass/override |

### 8.2 Best Practices

```swift
public class UserService {
    // Public API
    public func fetchUser(id: Int) async throws -> User { }
    
    // Internal helper
    func buildRequest(for id: Int) -> URLRequest { }
    
    // Private implementation detail
    private let session: URLSession
    private var cache: [Int: User] = [:]
}
```

### 8.3 Private Setters

```swift
public struct Counter {
    public private(set) var count = 0
    
    public mutating func increment() {
        count += 1
    }
}
```

---

## 9. Generics and Type Constraints

**Impact:** MEDIUM

### 9.1 Generic Functions

```swift
func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}
```

### 9.2 Type Constraints

```swift
func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
    array.firstIndex(of: value)
}

func decode<T: Decodable>(_ type: T.Type, from data: Data) throws -> T {
    try JSONDecoder().decode(type, from: data)
}
```

### 9.3 Where Clauses

```swift
func allMatch<C: Collection>(_ collection: C, predicate: (C.Element) -> Bool) -> Bool
    where C.Element: Equatable {
    collection.allSatisfy(predicate)
}

extension Array where Element: Numeric {
    func sum() -> Element {
        reduce(0, +)
    }
}
```

### 9.4 Opaque Types (some)

```swift
func makeCollection() -> some Collection {
    [1, 2, 3]
}

var body: some View {
    Text("Hello")
}
```

---

## 10. Property Wrappers

**Impact:** MEDIUM

### 10.1 Common SwiftUI Property Wrappers

| Wrapper | Use Case |
|---------|----------|
| `@State` | View-local mutable state |
| `@Binding` | Two-way connection to parent state |
| `@StateObject` | View-owned observable object |
| `@ObservedObject` | Passed-in observable object |
| `@EnvironmentObject` | Shared object from ancestor |
| `@Environment` | System environment values |
| `@Published` | Observable property in class |

### 10.2 Custom Property Wrappers

```swift
@propertyWrapper
struct Clamped<Value: Comparable> {
    private var value: Value
    let range: ClosedRange<Value>
    
    var wrappedValue: Value {
        get { value }
        set { value = min(max(newValue, range.lowerBound), range.upperBound) }
    }
    
    init(wrappedValue: Value, _ range: ClosedRange<Value>) {
        self.range = range
        self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
}

struct Settings {
    @Clamped(0...100) var volume: Int = 50
}
```

---

## Quick Reference

### Optionals

```swift
if let x = optional { }      // Safe unwrap
guard let x = optional else { return }  // Early exit
let x = optional ?? default  // Default value
optional?.method()           // Optional chaining
optional.map { transform($0) }  // Transform if present
```

### Common Patterns

```swift
// Defer for cleanup
func process() {
    let file = openFile()
    defer { closeFile(file) }
    // ... work with file
}

// Lazy initialization
lazy var expensive: ExpensiveObject = {
    ExpensiveObject()
}()

// Type inference
let numbers = [1, 2, 3]  // [Int]
let doubled = numbers.map { $0 * 2 }  // [Int]
```

### Closure Syntax

```swift
// Full syntax
let sorted = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 < s2
})

// Shortened
let sorted = names.sorted { $0 < $1 }

// Trailing closure
UIView.animate(withDuration: 0.3) {
    view.alpha = 0
}
```

---

## Checklist

### Safety
- [ ] No force unwrapping (`!`) except for IB outlets and known-safe cases
- [ ] All optionals handled with `if let`, `guard let`, or `??`
- [ ] No implicitly unwrapped optionals (`!`) in data models

### Memory
- [ ] Escaping closures capture `self` intentionally; use `[weak self]` or `[unowned self]` to avoid retain cycles when needed
- [ ] Delegate properties are `weak`
- [ ] No retain cycles between objects

### Concurrency
- [ ] Async functions used instead of completion handlers
- [ ] Mutable state shared across concurrency domains is isolated, often with actors
- [ ] Types crossing concurrency domains use `Sendable` when appropriate
- [ ] UI updates on `@MainActor`
- [ ] Task cancellation checked in long operations

### Access Control
- [ ] `private` used for implementation details
- [ ] `public` API is minimal and intentional
- [ ] No unnecessary `internal` exposure

### Naming
- [ ] Types use PascalCase
- [ ] Functions and variables use camelCase
- [ ] Booleans have `is`/`has`/`should` prefix
- [ ] Functions read like natural English

---

*Swift and Apple are trademarks of Apple Inc.*
