Swift Attributes (@語法)

在閱讀 Swift 程式碼時,你一定常看到以 @ 開頭的關鍵字,例如 @available, @discardableResult 或是 SwiftUI 中的 @State。這些稱為 Attributes (屬性),用來提供額外的資訊給編譯器,或是改變程式碼的行為。

本篇將介紹幾個最常見且實用的 Attributes。

@available: 檢查 API 可用性

這是開發 iOS App 最常用的 Attribute。用來標記某個類別、方法或屬性只能在特定的作業系統版本以上使用。

@available(iOS 15.0, *)
class NewFeatureView: UIView {
    // 只有在 iOS 15+ 才能使用這個類別
}

@available(macOS 12.0, iOS 15.0, *)
func useNewAPI() {
    // 同時指定多個平台
}

也可以用在 ifguard 語句中進行執行時檢查:

if #available(iOS 16.0, *) {
    // 使用 iOS 16 才有的新功能
} else {
    // 舊版本的 fallback 處理
}

@discardableResult: 忽略回傳值

預設情況下,如果一個函式有回傳值,但你呼叫後卻沒有使用它 (沒有賦值給變數),編譯器會發出警告。這有助於避免隱藏的 Bug。

但有些時候回傳值確實是「可選的」,例如一個更新資料的函式回傳是否成功,但我們可能不一定要檢查。

@discardableResult
func updateData() -> Bool {
    // ... 更新邏輯
    return true
}

// 因為加了 @discardableResult,即使沒接回傳值也不會有黃色警告
updateData() 

@main: 程式進入點

標記這個 Struct 或 Class 是整個應用程式的入口點 (Entry Point)。這在 SwiftUI App 和新的 Command Line Tool 中取代了傳統的 main.swift 檔案。

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

@propertyWrapper: 屬性包裝器

這是 Swift 5.1 引入的超強大功能,也是 SwiftUI (@State, @Binding, @Environment) 的核心基石。它允許你將屬性的「讀寫邏輯」封裝在一個獨立的型別中,然後重複使用。

定義一個自動將字串轉大寫的 Wrapper:

@propertyWrapper
struct Uppercased {
    private var value: String = ""
    
    var wrappedValue: String {
        get { value }
        set { value = newValue.uppercased() } // 寫入時自動轉大寫
    }
    
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue
    }
}

struct User {
    @Uppercased var username: String
}

var user = User(username: "hello")
print(user.username) // 輸出 "HELLO"

其他常見 Attributes

  • @objc: 讓 Swift 程式碼可以被 Objective-C 使用,或使用 Objective-C 的 Runtime 特性 (如 #selector)。
  • @frozen / @unknown default: 用於 Enum,處理未來可能新增 case 的相容性問題。
  • @testable: 讓單元測試 target 可以存取主 target 的 internal 成員。

熟悉這些 Attributes 能讓你寫出更強健、更符合 Swift 風格的程式碼。