特性

available

@available(iOS 13.0, *)
@available(iOSApplicationExtension, unavailable)
@available(swift 5)
@available(iOS, introduced: 13.0) // is only available in iOS 13.0 or newer
@available(iOS, deprecated: 13.0) // is deprecated: deprecated
@available(iOS, obsoleted: 13.0) // is unavailable in iOS
@available(*, deprecated, message: "deprecated")
@available(*, unavailable, renamed: "newname") // has been renamed to 'newname'

discardableResult

@discardableResult
func someFunction() -> Int {
    1
}

someFunction()

dynamicCallable

import JavaScriptCore

@dynamicCallable
struct JSFunctionWrapper {
    let value: JSValue

    func dynamicallyCall(withArguments args: [Any]) -> JSValue {
        value.call(withArguments: args)
    }
    
    func dynamicallyCall(withKeywordArguments pairs: [String: Any]) -> JSValue {
        value.call(withArguments: [pairs["a"]!, pairs["b"]!])
    }
}

let context: JSContext = JSContext()
context.evaluateScript(
"""
function sum(a, b) {
    return a + b
}
"""
)
let sumValue: JSValue = context.evaluateScript("sum")

let sum = JSFunctionWrapper(value: sumValue)
print(sum(1, 2)) // 3
print(sum(a: 1, b: 2)) // 3

dynamicMemberLookup

@dynamicMemberLookup
struct DynamicDict {
    let dict: [String: Int]
    
    subscript(dynamicMember key: String) -> Int? {
        dict[key]
    }
}

let dict = DynamicDict(dict: ["a": 1])
print(dict.a) // Optional(1)
print(dict.b) // nil

frozen

冻结对枚举的case和结构体的存储属性进行添加、删除、重新排序的操作,以保证发布二进制库的ABI兼容

main

@main
struct Main {
    static func main() {
        print("Hello, world!")
    }
}

nonobjc

@objcMembers
public class OCBridge: NSObject {
    @nonobjc public func onlyInSwift() {
        
    }
}

objc

public class OCBridge: NSObject {
    @objc func compatibleMethod() {
        
    }
    
    @objc(ocMethod)
    func swiftMethod() {
        
    }
}

objcMembers

@objcMembers
public class OCBridge: NSObject {
    
}

propertyWrapper

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T
    
    init(wrappedValue defaultValue: T, _ key: String) {
        self.key = key
        self.defaultValue = defaultValue
    }
    
    var wrappedValue: T {
        get {
            UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }

        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
    
    var projectedValue: T? {
        UserDefaults.standard.object(forKey: key) as? T
    }
}

struct AppConfig {
    @UserDefault("hasAppLaunchedOnce") static var hasAppLaunchedOnce: Bool = false
}

var isFirstLaunch: Bool {
    if AppConfig.hasAppLaunchedOnce {
        return false
    }

    AppConfig.hasAppLaunchedOnce = true
    return true
}

print(isFirstLaunch) // true false
print(AppConfig.hasAppLaunchedOnce) // false true
print(AppConfig.$hasAppLaunchedOnce) // Optional(false) Optional(true)

resultBuilder

@resultBuilder struct Paragraph {
    static func buildBlock(_ sentences: String...) -> String {
        sentences.joined(separator: "\n")
    }
}

@Paragraph
func makeParagraph() -> String {
    "resultBuilder"
    "hello"
    "world"
}

print(makeParagraph())
// resultBuilder
// hello
// world