预处理和预编译

Swift与C、C++、Objective-C不同,它没有预处理过程。运用的是预编译来解析和处理源代码-即在编译时处理代码。
预编译包括如下几个功能

  1. 编译特性(attribute)
  2. 编译标志(条件编译)
  3. 查看API的可⽤性

编译特性(attribute)

  • Swift的特性(attribute)与C/C++的 __attribute__ ⾮常类似
  • 润饰目标、函数和类型,指定编译时⾏为。
  • @ 符号开端,后⾯紧跟特性名。
@attribute(args)
func function() {
} 

下面是一些常用的特性

  1. available
  • 表明在系统渠道上的可用性(iOS、macOS、watchOS、tvOS、swift, ⽤ * 代表所有渠道)
// MyStruct只能在iOS 14+ macOS 12.0+, Swift 5.0+ 版别运用
@available(swift 5.0) 
@available(iOS 14, macOS 12.0, *) 
struct MyStruct { 
}
  • 哪个版别开端可⽤(introduced),哪个版别开端抛弃(deprecated),哪个版别不行⽤(obsoleted)。
/// myTest函数iOS 13开端引⼊, 14开端抛弃,15不行用
@available(iOS, introduced: 13, deprecated: 14, obsoleted: 15, message: "The function is deprecated!") 
func myTest() { 
}
  1. discardableResult

润饰带有返回值的办法,表明办法返回值能够丢掉, 不会出现返回值未被使⽤警告

@discardableResult
func foo(a: Int) -> Int {
    return a + 1 
}
foo(a: 10)
  1. objc
  • 运用@objc 把类、办法、属性暴露给Objective-C
  • Protocol 的办法加上@objc表明optional(非有必要完成),
@objc
protocol MyProt {
    // 此办法有必要完成
    func method()
    // 不是有必要完成
    @objc
    optional func foo()
}
  1. autoclosure

将表达式⾃动封装为不带参数的闭包。

func logIfTrue(_ predicate: @autoclosure () -> Bool) {
    if predicate() {
        print(#function)
    }
}
logIfTrue(1 < 2)
  1. convention
  • @convention(swift): 表明Swift闭包,Swift标准函数调用约好
  • @convention(block):相当于OC的block的闭包
  • @convention(c):相当于c函数指针的闭包
/// 作为Objective-C目标使⽤ 
let ref2: @convention(block) (Int) -> Void = 
{(a: Int) -> Void in 
    x -= a 
}
/// C函数没有执⾏上下⽂,因此⽆法捕获局部目标
let ref3: @convention(c) (Int) -> Void = 
{ (a: Int) -> Void in 
    print("a + 1 = \(a + 1)") 
}
  1. escaping

逃逸闭包, 闭包作为函数形参会在稍后执⾏,该闭包的⽣命周期将延伸到函数履行后。

编译器强制你显式的运用 self,从而避免循环引证问题。

  1. inline

表明内联函数, 内联函数的完成直接内嵌在调用途,取代函数调用,提高履行功率。

  • never 表⽰函数何时都不应该被內联。
  • __always 表⽰总是被內联
@inline(never)
func noinlineFunc() { 
    print("Never inlined!") 
}
@inline(__always) 
func alwaysinlineFunc() { 
    print("always inlined!") 
}

Swift编译器会依据编译上下⽂⾃⾏决议函数是否需要内联

  1. _silgen_name

表明是⼀个遵从C语⾔标准ABI的函数, 用于在Swift中完成标准C函数的功能,

// 声明具有外部连接的C函数CFunc。 
// CFunc函数能够在C代码中无缝调用
@_silgen_name("CFunc") 
func CFunc(_: Int) -> Int {
    return 0
}

这个特性关于Swift的⽣态⼗分重要,Swift的ABI能够与C保持兼容,即能够⽤C的地⽅就能使⽤Swift

编译标志(条件编译)

Swift编译器同C/C++的类似,能够设置编译选项。

-D DEBUG,表明在调试时新增DEBUG编译标志,

运用#if ... #else ... #endif 做条件编译, 没有 #ifdef#ifndef这种形式。

func debug_log(str: String) {
    #if DEBUG 
        print(str) 
    #endif 
}
debug_log(str: "Hello, world!!")

使⽤ &&、||、! 做联合判断。

#if (DEBUG && !os(iOS)) || arch(x86_64)
print("Hello, world!") 
#elseif arch(arm64) 
print("Thanks world!") 
#else 
print("Others...") 
#endif

Swift⽀持如下预先定义的条件编译

  1. os()

表⽰操作系统环境。有效参数:macOS、iOS、watchOS、tvOS、Linux、FreeBS

  1. arch()

表⽰处理器环境。有效参数:i386,x86_64,arm,arm64。

  1. swift()

表⽰Swift语⾔版别。⽐如:swift(>=5.0) 表⽰Swift版别从5.0开端起。

查看API的可⽤性

if 与#available联⽤,构成⼀个运⾏时渠道查看代码。如果指定的渠道以及系统版别成⽴,就执⾏ if 块中的代码

// iOS 10 以后才能够运用这种block定义timer的办法
if #available(iOS 10, *) {
    Timer.scheduledTimer(withTimeInterval:1.0,repeats:false) { 
    (timer: Timer) -> Void in 
        print("timer fired!") 
    } 
} else {
    Timer.scheduledTimer(timeInterval:1.0,target:self,
    selector:#selector(timerHandler(:)),userInfo:nil,repeats:false)
}

#available的用法和参数与@available很相似。