| name | swift-coding-standards |
| category | coding-standards |
| difficulty | intermediate |
| estimated_time | 45 minutes |
| description | Master Swift coding standards with Apple's guidelines, protocol-oriented design, and modern concurrency patterns |
| version | 1.0.0 |
| tags | ["swift","ios","macos","mobile","apple"] |
| related_skills | ["kotlin-coding-standards","typescript-coding-standards"] |
Swift Coding Standards
Learn Once, Write Anywhere: Master Swift coding standards for iOS, macOS, watchOS, and tvOS development with protocol-oriented design, value semantics, and modern concurrency.
Level 1: Quick Reference
Optionals Cheat Sheet
if let name = name { print("Hello, \(name)") }
guard let age = age else { return }
let displayName = name ?? "Anonymous"
let count = user?.profile?.posts?.count
Essential Patterns
protocol Drawable {
var color: Color { get set }
func draw()
}
extension Drawable {
func draw() { print("Drawing with \(color)") }
}
struct Circle: Drawable {
var color: Color
var radius: Double
}
let doubled = numbers.map { $0 * 2 }
@State private var isPresented = false
Naming Conventions
class UserProfileViewController { }
struct NetworkRequest { }
protocol DataSource { }
var userName: String
func fetchUserProfile() { }
var isLoading: Bool
var hasCompletedOnboarding: Bool
Pre-Commit Checklist
Level 2: Implementation Guide
1. Optionals and Safety
Swift's optional system eliminates null pointer exceptions through compile-time safety.
if let unwrapped = optionalValue {
print(unwrapped)
}
if let name = userName, let age = userAge, age >= 18 {
print("\(name) is an adult")
}
func processUser(_ user: User?) {
guard let user = user else { return }
print(user.name)
}
let uppercasedName = userName.map { $0.uppercased() }
let userID = userIDString.flatMap { Int($0) }
2. Protocol-Oriented Design
Swift favors composition over inheritance through protocols.
protocol DataStore {
func save<T: Codable>(_ item: T, key: String) throws
func load<T: Codable>(key: String) throws -> T?
}
extension Collection {
func chunked(into size: Int) -> [[Element]] {
stride(from: 0, to: count, by: size).map {
Array(self[$0..<Swift.min($0 + size, count)])
}
}
}
protocol Repository {
associatedtype Item
func fetchAll() async throws -> [Item]
func save(_ item: Item) async throws
}
3. Value Types vs Reference Types
struct User {
var name: String
var email: String
}
class NetworkManager {
static let shared = NetworkManager()
}
enum LoadingState {
case idle, loading
case success(Data)
case failure(Error)
}
4. Memory Management with ARC
class Apartment {
weak var tenant: Person?
}
onComplete = { [weak self] in
self?.processResult()
}
class CreditCard {
unowned let customer: Customer
}
5. Error Handling
enum NetworkError: Error {
case invalidURL
case noConnection
case serverError(statusCode: Int)
}
func fetchUser(id: Int) throws -> User {
guard let url = URL(string: "https://api.example.com/users/\(id)") else {
throw NetworkError.invalidURL
}
}
do {
let user = try fetchUser(id: 123)
} catch NetworkError.serverError(let code) {
print("Server error: \(code)")
} catch {
print("Unknown error: \(error)")
}
6. Modern Concurrency (async/await)
func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
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) }
}
}
actor BankAccount {
private var balance: Double = 0
func deposit(_ amount: Double) { balance += amount }
func getBalance() -> Double { balance }
}
@MainActor
class ViewModel: ObservableObject {
@Published var isLoading = false
@Published var users: [User] = []
}
7. Testing with XCTest
import XCTest
@testable import MyApp
final class UserManagerTests: XCTestCase {
var sut: UserManager!
var mockStore: MockDataStore!
override func setUp() {
super.setUp()
mockStore = MockDataStore()
sut = UserManager(store: mockStore)
}
func testFetchUser_Success() async throws {
mockStore.userToReturn = User(id: 1, name: "John")
let user = try await sut.fetchUser(id: 1)
XCTAssertEqual(user.name, "John")
XCTAssertTrue(mockStore.fetchUserCalled)
}
}
Level 3: Deep Dive Resources
For comprehensive examples and advanced patterns, see REFERENCE.md.
Advanced Topics Covered in REFERENCE.md
- Generics: Type constraints, associated types, type erasure
- Property Wrappers: @State, @Binding, custom wrappers
- Result Builders: Creating custom DSLs
- SwiftUI Architecture: MVVM, state management, navigation
- Performance Optimization: Instruments profiling, COW patterns
- Complete Code Examples: Network layer, repositories, mocks
Quick Setup
brew install swiftlint
if which swiftlint >/dev/null; then swiftlint; fi
swiftlint lint --config .swiftlint.yml
Official Documentation
Learning Path
- Week 1-2: Optionals, protocols, value/reference types
- Week 3-4: Memory management, error handling, testing
- Week 5-6: Async/await, actors, structured concurrency
- Week 7-8: SwiftUI, Combine, advanced patterns
Bundled Resources
config/.swiftlint.yml - SwiftLint configuration
templates/ViewModel.swift - MVVM template
templates/NetworkService.swift - Async network layer
templates/TestCase.swift - XCTest template
Remember: Swift is designed for safety, speed, and expressiveness. Embrace optionals, leverage protocols, and write tests.