预处理和预编译
Swift与C、C++、Objective-C不同,它没有预处理
过程。运用的是预编译
来解析和处理源代码-即在编译时处理代码。
预编译包括如下几个功能
- 编译特性(attribute)
- 编译标志(条件编译)
- 查看API的可⽤性
编译特性(attribute)
- Swift的特性(attribute)与C/C++的
__attribute__
⾮常类似 - 润饰
目标、函数和类型
,指定编译时⾏为。 - 由
@
符号开端,后⾯紧跟特性名。
@attribute(args)
func function() {
}
下面是一些常用的特性
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() {
}
discardableResult
润饰带有返回值的办法,表明办法返回值能够丢掉, 不会出现返回值未被使⽤警告
。
@discardableResult
func foo(a: Int) -> Int {
return a + 1
}
foo(a: 10)
objc
- 运用@objc 把类、办法、属性
暴露给Objective-C
- Protocol 的办法加上@objc表明optional(非有必要完成),
@objc
protocol MyProt {
// 此办法有必要完成
func method()
// 不是有必要完成
@objc
optional func foo()
}
autoclosure
将表达式⾃动封装为不带参数的闭包。
func logIfTrue(_ predicate: @autoclosure () -> Bool) {
if predicate() {
print(#function)
}
}
logIfTrue(1 < 2)
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)")
}
escaping
逃逸闭包, 闭包作为函数形参会在稍后执⾏,该闭包的⽣命周期将延伸到函数履行后。
编译器强制你显式的运用 self
,从而避免循环引证问题。
inline
表明内联函数, 内联函数的完成直接内嵌在调用途,取代函数调用,提高履行功率。
-
never
表⽰函数何时都不应该被內联。 -
__always
表⽰总是被內联
@inline(never)
func noinlineFunc() {
print("Never inlined!")
}
@inline(__always)
func alwaysinlineFunc() {
print("always inlined!")
}
Swift编译器会依据编译上下⽂⾃⾏决议函数是否需要内联
_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⽀持如下预先定义的条件编译
os()
表⽰操作系统环境
。有效参数:macOS、iOS、watchOS、tvOS、Linux、FreeBS
arch()
表⽰处理器环境
。有效参数:i386,x86_64,arm,arm64。
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
很相似。