Initial commit: add all skills files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-10 16:52:49 +08:00
commit 6487becf60
396 changed files with 108871 additions and 0 deletions

View File

@@ -0,0 +1,741 @@
# 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]] {
stride(from: 0, to: count, by: size).map {
Array(self[$0..<Swift.min($0 + size, count)])
}
}
}
```
### 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 for shared mutable state, identity matters:
```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
```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
### 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
- [ ] Closures use `[weak self]` when capturing self in escaping closures
- [ ] Delegate properties are `weak`
- [ ] No retain cycles between objects
### Concurrency
- [ ] Async functions used instead of completion handlers
- [ ] Actors protect shared mutable state
- [ ] 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.*