1. Swift函数基础概述
在Swift编程语言中,函数是构建程序的基本模块,它们封装了特定任务的代码块,可以在程序中多次调用。Swift的函数语法既灵活又强大,支持参数标签、默认参数值、可变参数等多种特性,这使得Swift函数比其他语言的函数更具表现力。
提示:Swift 5.9引入的Parameter-Free Attention Network(SPAN)机制虽然与基础函数无关,但了解Swift前沿发展有助于拓宽视野。
函数在Swift中是一等公民(first-class citizens),这意味着:
- 函数可以作为参数传递给其他函数
- 函数可以作为其他函数的返回值
- 函数可以赋值给变量或常量
- 函数可以嵌套在其他函数中
这种特性为函数式编程范式提供了强大支持,也是Swift语言设计的重要特点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 函数声明与基本语法
2.1 函数定义格式
Swift函数的基本定义语法如下:
swift复制func 函数名(参数名1: 参数类型, 参数名2: 参数类型) -> 返回类型 {
// 函数体
return 返回值
}
例如,一个简单的加法函数:
swift复制func add(a: Int, b: Int) -> Int {
return a + b
}
2.2 函数调用
调用上述函数的方式如下:
swift复制let sum = add(a: 5, b: 3) // 结果为8
Swift强制要求在调用函数时必须明确写出参数标签(argument labels),这增强了代码的可读性。如果你来自其他编程语言背景,这一点可能需要适应。
2.3 无返回值函数
如果函数不需要返回值,可以省略返回类型声明:
swift复制func greet(name: String) {
print("Hello, \(name)!")
}
实际上,这种函数隐式返回一个Void类型的特殊值,等同于空元组()。
3. 函数参数高级特性
3.1 参数标签与参数名
Swift允许为函数参数指定外部标签和内部名称:
swift复制func greet(to name: String) {
print("Hello, \(name)!")
}
greet(to: "Alice") // 使用外部标签"to"
在这个例子中:
to是外部参数标签(用在函数调用时)name是内部参数名(用在函数体内)
如果省略外部标签,可以使用下划线_:
swift复制func greet(_ name: String) {
print("Hello, \(name)!")
}
greet("Bob") // 不需要参数标签
3.2 默认参数值
Swift函数支持为参数提供默认值:
swift复制func greet(name: String = "Guest") {
print("Hello, \(name)!")
}
greet() // 输出"Hello, Guest!"
greet(name: "Tom") // 输出"Hello, Tom!"
注意:带有默认值的参数通常放在参数列表的最后,这不是强制要求但是一种良好实践。
3.3 可变参数
使用...语法可以定义接受多个同类型参数的函数:
swift复制func average(_ numbers: Double...) -> Double {
var total = 0.0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
print(average(1, 2, 3, 4, 5)) // 输出3.0
可变参数在函数内部表现为对应类型的数组。一个函数最多只能有一个可变参数。
3.4 输入输出参数
使用inout关键字可以创建能修改外部变量值的参数:
swift复制func swapValues(_ a: inout Int, _ b: inout Int) {
let temp = a
a = b
b = temp
}
var x = 5
var y = 10
swapValues(&x, &y) // 调用时需要使用&符号
print(x, y) // 输出10, 5
重要提示:inout参数不能有默认值,可变参数不能标记为inout。
4. 函数类型与高级用法
4.1 函数类型
每个函数都有特定的类型,由参数类型和返回类型组成。例如:
swift复制func add(a: Int, b: Int) -> Int { ... }
// 函数类型为 (Int, Int) -> Int
func greet() { ... }
// 函数类型为 () -> Void
函数类型可以像其他类型一样使用:
swift复制var mathFunction: (Int, Int) -> Int = add
let result = mathFunction(2, 3) // 结果为5
4.2 函数作为参数
函数可以作为参数传递给其他函数:
swift复制func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(add, 3, 5) // 输出"Result: 8"
4.3 函数作为返回值
函数也可以返回其他函数:
swift复制func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
let currentFunction = chooseStepFunction(backward: true)
print(currentFunction(3)) // 输出2
4.4 嵌套函数
Swift支持在函数内部定义其他函数:
swift复制func outerFunction() {
var x = 10
func innerFunction() {
x += 5
}
innerFunction()
print(x) // 输出15
}
嵌套函数可以访问外部函数的变量,这在某些算法实现中非常有用。
5. 闭包基础
5.1 闭包表达式
闭包是自包含的函数代码块,Swift中的闭包与函数非常相似:
swift复制let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let sortedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 < s2
})
闭包表达式可以使用多种简写形式:
swift复制// 类型推断
let sortedNames = names.sorted(by: { s1, s2 in return s1 < s2 })
// 单表达式闭包隐式返回
let sortedNames = names.sorted(by: { s1, s2 in s1 < s2 })
// 参数名称缩写
let sortedNames = names.sorted(by: { $0 < $1 })
// 运算符方法
let sortedNames = names.sorted(by: <)
5.2 尾随闭包
当闭包是函数的最后一个参数时,可以使用尾随闭包语法:
swift复制let sortedNames = names.sorted { $0 < $1 }
如果函数只有闭包一个参数,甚至可以省略括号:
swift复制let digitNames = [0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four"]
let numbers = [16, 58, 510]
let strings = numbers.map {
var number = $0
var output = ""
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings为["OneSix", "FiveEight", "FiveOneZero"]
6. 错误处理与函数
6.1 抛出错误的函数
使用throws关键字标记可能抛出错误的函数:
swift复制enum FileError: Error {
case fileNotFound
case permissionDenied
}
func readFile(at path: String) throws -> String {
// 模拟文件操作
if path.isEmpty {
throw FileError.fileNotFound
}
return "File content"
}
6.2 调用可能抛出错误的函数
使用do-catch语句调用可能抛出错误的函数:
swift复制do {
let content = try readFile(at: "/path/to/file")
print(content)
} catch FileError.fileNotFound {
print("File not found")
} catch {
print("Other error: \(error)")
}
6.3 可选错误处理
如果只关心成功结果,可以使用try?将结果转换为可选值:
swift复制let content = try? readFile(at: "/invalid/path")
// content为nil
或者使用try!在确定不会出错时强制解包:
swift复制let content = try! readFile(at: "/valid/path")
// 如果确实出错,会触发运行时错误
7. 函数式编程实践
7.1 高阶函数应用
Swift标准库提供了丰富的高阶函数:
swift复制let numbers = [1, 2, 3, 4, 5]
// map - 转换
let squared = numbers.map { $0 * $0 } // [1, 4, 9, 16, 25]
// filter - 过滤
let evens = numbers.filter { $0 % 2 == 0 } // [2, 4]
// reduce - 归约
let sum = numbers.reduce(0, +) // 15
7.2 自定义高阶函数
我们可以创建自己的高阶函数:
swift复制func applyTwice(_ f: (Int) -> Int, to x: Int) -> Int {
return f(f(x))
}
let result = applyTwice({ $0 * 2 }, to: 3) // 12 (3*2=6, 6*2=12)
7.3 函数组合
通过函数组合可以创建更复杂的操作:
swift复制func compose<A, B, C>(_ f: @escaping (B) -> C, _ g: @escaping (A) -> B) -> (A) -> C {
return { x in f(g(x)) }
}
let double = { $0 * 2 }
let square = { $0 * $0 }
let doubleThenSquare = compose(square, double)
print(doubleThenSquare(3)) // 36 (3*2=6, 6*6=36)
8. 函数性能优化
8.1 @inline属性
Swift编译器会自动决定是否内联函数,但我们可以提供提示:
swift复制@inline(__always) func veryFastOperation() { ... }
@inline(never) func largeFunction() { ... }
8.2 避免过度抽象
虽然函数抽象是良好的编程实践,但在性能关键路径上要权衡:
swift复制// 可能影响性能的抽象
func processElement(_ x: Int) -> Int {
return x * x + x
}
let result = bigArray.map(processElement).reduce(0, +)
// 更高效的版本
var sum = 0
for x in bigArray {
sum += x * x + x
}
8.3 使用@autoclosure延迟求值
@autoclosure可以延迟表达式求值:
swift复制func logIfTrue(_ condition: @autoclosure () -> Bool) {
if condition() {
print("True")
}
}
logIfTrue(2 > 1) // 表达式2>1不会立即求值
9. Swift函数最新特性
9.1 Swift 5.9中的新特性
Swift 5.9引入了Parameter-Free Attention Network(SPAN)等新概念,虽然主要与机器学习相关,但也影响了函数设计模式:
swift复制// 使用Swift新特性简化回调处理
func fetchData() async throws -> Data {
let url = URL(string: "https://api.example.com/data")!
let (data, _) = try await URLSession.shared.data(from: url)
return data
}
9.2 SwiftUI中的函数应用
在SwiftUI中,函数式编程范式得到广泛应用:
swift复制struct ContentView: View {
@State private var isOn = false
var body: some View {
Toggle("Switch", isOn: $isOn)
.padding()
.background(isOn ? Color.green : Color.red)
.animation(.default, value: isOn)
}
}
9.3 Swift并发模型中的函数
Swift的并发模型引入了async/await语法,改变了传统回调函数的编写方式:
swift复制func fetchUserAndPosts(userId: Int) async throws -> (User, [Post]) {
async let user = fetchUser(id: userId)
async let posts = fetchPosts(for: userId)
return try await (user, posts)
}
10. 常见问题与解决方案
10.1 参数标签混淆
问题:混淆参数标签和参数名导致编译错误。
解决方案:
- 明确区分外部参数标签和内部参数名
- 使用_省略不需要的外部标签
- 保持API设计一致性
10.2 闭包循环引用
问题:闭包捕获self导致循环引用。
解决方案:
swift复制class MyClass {
var value = 0
lazy var closure: () -> Void = { [weak self] in
guard let self = self else { return }
print(self.value)
}
}
10.3 可变参数类型限制
问题:尝试在可变参数中使用不同类型。
解决方案:
- 使用数组代替
- 定义枚举包装不同类型
- 考虑使用泛型函数
10.4 错误处理遗漏
问题:忘记处理可能抛出的错误。
解决方案:
- 使用do-catch明确处理错误
- 使用try?或try!明确表达意图
- 文档中注明可能抛出的错误类型
10.5 函数性能问题
问题:函数调用成为性能瓶颈。
解决方案:
- 使用@inline(__always)提示编译器
- 减少函数抽象层级
- 考虑使用内联代码或宏
11. 最佳实践与代码风格
11.1 命名规范
- 函数名使用小驼峰命名法
- 方法名应描述其行为或返回值
- 避免含糊的名称如"process"或"handle"
好的示例:
swift复制func calculateArea(width: Double, height: Double) -> Double
func loadUserProfile(from url: URL) async throws -> UserProfile
不好的示例:
swift复制func doSomething(a: Double, b: Double) -> Double
func getData(url: URL) async throws -> UserProfile
11.2 参数设计
- 限制参数数量(通常不超过5个)
- 为参数提供有意义的标签
- 将相关参数组合为结构体
重构示例:
swift复制// 重构前
func createUser(name: String, email: String, age: Int, isAdmin: Bool)
// 重构后
struct UserInfo {
let name: String
let email: String
let age: Int
let isAdmin: Bool
}
func createUser(_ info: UserInfo)
11.3 文档注释
使用Markdown格式编写文档注释:
swift复制/// 计算两个数的和
/// - Parameters:
/// - a: 第一个加数
/// - b: 第二个加数
/// - Returns: 两个参数的和
/// - Complexity: O(1)
/// - Note: 对于大数相加,注意整数溢出问题
func add(a: Int, b: Int) -> Int {
return a + b
}
11.4 函数长度控制
- 理想情况下函数不超过20行
- 过长的函数应考虑拆分为多个小函数
- 使用嵌套函数组织复杂逻辑
11.5 测试友好设计
- 避免函数有隐藏的依赖
- 使函数尽可能纯(无副作用)
- 依赖通过参数注入而非全局访问
swift复制// 不易测试的版本
func saveData() {
let db = Database.shared
// ...
}
// 易于测试的版本
func saveData(to database: Database) {
// ...
}
12. 实战案例:构建实用函数库
12.1 日期处理函数
swift复制import Foundation
/// 格式化日期为字符串
/// - Parameters:
/// - date: 要格式化的日期
/// - format: 日期格式字符串,默认"yyyy-MM-dd"
/// - Returns: 格式化后的字符串
func formatDate(_ date: Date, format: String = "yyyy-MM-dd") -> String {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: date)
}
/// 从字符串解析日期
/// - Parameters:
/// - string: 日期字符串
/// - format: 预期的日期格式
/// - Returns: 解析后的日期,解析失败返回nil
func parseDate(from string: String, format: String) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.date(from: string)
}
12.2 数学工具函数
swift复制/// 计算数字的平均值
/// - Parameter numbers: 要计算平均值的数字集合
/// - Returns: 平均值
func average<T: FloatingPoint>(_ numbers: T...) -> T {
guard !numbers.isEmpty else { return 0 }
return numbers.reduce(0, +) / T(numbers.count)
}
/// 线性插值
/// - Parameters:
/// - start: 起始值
/// - end: 结束值
/// - t: 插值因子(0...1)
/// - Returns: 插值结果
func lerp<T: FloatingPoint>(from start: T, to end: T, t: T) -> T {
return start + (end - start) * t
}
12.3 字符串处理函数
swift复制/// 检查字符串是否是有效的电子邮件地址
/// - Parameter email: 要检查的字符串
/// - Returns: 如果是有效电子邮件则返回true
func isValidEmail(_ email: String) -> Bool {
let pattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
return predicate.evaluate(with: email)
}
/// 生成随机字符串
/// - Parameters:
/// - length: 字符串长度
/// - characters: 可选,允许的字符集
/// - Returns: 随机生成的字符串
func randomString(length: Int, characters: String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") -> String {
var result = ""
for _ in 0..<length {
let randomIndex = Int.random(in: 0..<characters.count)
let index = characters.index(characters.startIndex, offsetBy: randomIndex)
result.append(characters[index])
}
return result
}
12.4 网络请求封装
swift复制import Foundation
/// 执行GET请求
/// - Parameters:
/// - url: 请求URL
/// - headers: 可选,请求头字典
/// - Returns: 解码后的响应数据
func fetch<T: Decodable>(from url: URL, headers: [String: String]? = nil) async throws -> T {
var request = URLRequest(url: url)
request.httpMethod = "GET"
headers?.forEach { request.addValue($0.value, forHTTPHeaderField: $0.key) }
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw URLError(.badServerResponse)
}
return try JSONDecoder().decode(T.self, from: data)
}
13. 调试与测试技巧
13.1 调试复杂函数
- 使用
dump()函数打印复杂对象 - 在函数入口和出口添加打印语句
- 使用条件断点调试特定情况
swift复制func complexCalculation(input: [Int]) -> Int {
print("Function input: \(input)")
defer { print("Calculation completed") }
// ...复杂计算逻辑...
return result
}
13.2 单元测试函数
为函数编写单元测试示例:
swift复制import XCTest
class MathFunctionsTests: XCTestCase {
func testAddFunction() {
XCTAssertEqual(add(a: 2, b: 3), 5)
XCTAssertEqual(add(a: -1, b: 1), 0)
XCTAssertEqual(add(a: 0, b: 0), 0)
}
func testAverageFunction() {
XCTAssertEqual(average(1.0, 2.0, 3.0), 2.0)
XCTAssertEqual(average(5.0), 5.0)
XCTAssertEqual(average(), 0.0)
}
}
13.3 性能测试关键函数
使用XCTest测量函数性能:
swift复制func testPerformanceOfCriticalFunction() {
let testData = (1...1_000_000).map { _ in Int.random(in: 1...100) }
measure {
_ = testData.map { somePerformanceCriticalFunction($0) }
}
}
13.4 使用断言验证前提条件
在函数中添加前提条件检查:
swift复制func sqrt(_ x: Double) -> Double {
precondition(x >= 0, "不能对负数开平方")
// ...计算逻辑...
}
14. 跨平台开发注意事项
14.1 平台特定函数
使用条件编译处理平台差异:
swift复制func getDeviceInfo() -> String {
#if os(macOS)
return "macOS Device"
#elseif os(iOS)
return "iOS Device"
#elseif os(watchOS)
return "watchOS Device"
#elseif os(tvOS)
return "tvOS Device"
#else
return "Unknown Apple Device"
#endif
}
14.2 可用性检查
使用@available标记特定平台可用的函数:
swift复制@available(iOS 15.0, macOS 12.0, *)
func useNewFrameworkFeature() {
// 使用新API
}
14.3 处理不同平台的API差异
封装平台差异:
swift复制func openURL(_ url: URL) {
#if os(iOS)
UIApplication.shared.open(url)
#elseif os(macOS)
NSWorkspace.shared.open(url)
#endif
}
15. 函数优化进阶技巧
15.1 使用@_specialize优化性能
对于性能关键函数,可以使用编译器指令优化特定类型:
swift复制@_specialize(where T == Int)
@_specialize(where T == Double)
func process<T: Numeric>(_ value: T) -> T {
return value * value
}
15.2 内存访问优化
对于大数据处理,优化内存访问模式:
swift复制func processLargeArray(_ array: [Double]) -> [Double] {
var result = [Double](repeating: 0.0, count: array.count)
array.withUnsafeBufferPointer { input in
result.withUnsafeMutableBufferPointer { output in
for i in 0..<input.count {
output[i] = sqrt(input[i])
}
}
}
return result
}
15.3 使用SIMD优化数值计算
对于数值密集型计算,使用SIMD指令:
swift复制import simd
func simdAddition(_ a: [Float], _ b: [Float]) -> [Float] {
precondition(a.count == b.count)
var result = [Float](repeating: 0, count: a.count)
for i in stride(from: 0, to: a.count, by: 4) {
let end = min(i + 4, a.count)
let aVec = simd_float4(array: Array(a[i..<end]))
let bVec = simd_float4(array: Array(b[i..<end]))
let rVec = aVec + bVec
result.replaceSubrange(i..<end, with: rVec.array)
}
return result
}
extension simd_float4 {
init(array: [Float]) {
self.init(
array.count > 0 ? array[0] : 0,
array.count > 1 ? array[1] : 0,
array.count > 2 ? array[2] : 0,
array.count > 3 ? array[3] : 0
)
}
var array: [Float] {
return [x, y, z, w]
}
}
16. 函数与协议结合使用
16.1 协议中定义函数要求
swift复制protocol DataFetcher {
func fetchData() async throws -> Data
func parseData(_ data: Data) throws -> Any
}
16.2 协议扩展提供默认实现
swift复制extension DataFetcher {
func fetchAndParse() async throws -> Any {
let data = try await fetchData()
return try parseData(data)
}
}
16.3 函数作为协议关联类型
swift复制protocol Processor {
associatedtype Input
associatedtype Output
var process: (Input) -> Output { get }
}
struct StringToIntProcessor: Processor {
let process: (String) -> Int = { Int($0) ?? 0 }
}
17. 函数与泛型结合
17.1 基本泛型函数
swift复制func swapValues<T>(_ a: inout T, _ b: inout T) {
let temp = a
a = b
b = temp
}
17.2 类型约束泛型函数
swift复制func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {
for (index, item) in array.enumerated() {
if item == value {
return index
}
}
return nil
}
17.3 泛型where子句
swift复制func processSequence<S: Sequence>(_ sequence: S) where S.Element: Numeric {
let sum = sequence.reduce(0, +)
print("Sum: \(sum)")
}
18. 函数与属性包装器
18.1 使用属性包装器简化函数参数处理
swift复制@propertyWrapper
struct Clamped<T: Comparable> {
private var value: T
private let range: ClosedRange<T>
var wrappedValue: T {
get { value }
set { value = min(max(range.lowerBound, newValue), range.upperBound) }
}
init(wrappedValue: T, _ range: ClosedRange<T>) {
self.range = range
self.value = min(max(range.lowerBound, wrappedValue), range.upperBound)
}
}
func setTemperature(@Clamped(0...100) _ temp: Int) {
print("Temperature set to \(temp)")
}
setTemperature(50) // 正常
setTemperature(150) // 实际存储100
19. 函数与Swift并发模型
19.1 异步函数
swift复制func fetchUser(id: Int) async throws -> User {
let url = URL(string: "https://api.example.com/users/\(id)")!
let (data, _) = try await URLSession.shared.data(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
19.2 异步序列处理
swift复制func processLines(from file: URL) async throws {
let handle = try FileHandle(forReadingFrom: file)
for try await line in handle.bytes.lines {
print("Processing: \(line)")
// 模拟耗时处理
try await Task.sleep(nanoseconds: 100_000_000)
}
}
19.3 任务组并行处理
swift复制func fetchMultipleUsers(ids: [Int]) async throws -> [User] {
try await withThrowingTaskGroup(of: User.self) { group in
for id in ids {
group.addTask {
try await fetchUser(id: id)
}
}
var users = [User]()
for try await user in group {
users.append(user)
}
return users.sorted { $0.id < $1.id }
}
}
20. 函数式编程模式实践
20.1 柯里化函数
swift复制func curryAdd(_ a: Int) -> (Int) -> Int {
return { b in a + b }
}
let addFive = curryAdd(5)
print(addFive(3)) // 输出8
20.2 函数部分应用
swift复制func greet(greeting: String, name: String) -> String {
return "\(greeting), \(name)!"
}
let sayHello = { name in greet(greeting: "Hello", name: name) }
print(sayHello("Alice")) // 输出"Hello, Alice!"
20.3 惰性求值函数
swift复制func lazyFilter<T>(_ array: [T], _ predicate: @escaping (T) -> Bool) -> () -> [T] {
return {
var result = [T]()
for element in array {
if predicate(element) {
result.append(element)
}
}
return result
}
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let getEvens = lazyFilter(numbers) { $0 % 2 == 0 }
// 实际计算推迟到调用时
print(getEvens()) // 输出[2, 4, 6, 8, 10]
21. 函数与SwiftUI视图构建
21.1 视图构建函数
swift复制func makeHeader(title: String) -> some View {
Text(title)
.font(.largeTitle)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
struct ContentView: View {
var body: some View {
VStack {
makeHeader(title: "Welcome")
Text("Main content goes here")
}
}
}
21.2 视图修饰函数
swift复制extension View {
func cardStyle() -> some View {
self
.padding()
.background(Color.white)
.cornerRadius(10)
.shadow(radius: 5)
}
}
struct ContentView: View {
var body: some View {
Text("Card Content")
.cardStyle()
}
}
21.3 视图生成函数
swift复制func makeListItems(for items: [String]) -> [some View] {
items.map { item in
HStack {
Image(systemName: "circle.fill")
.foregroundColor(.blue)
Text(item)
}
}
}
struct ListView: View {
let items = ["Item 1", "Item 2", "Item 3"]
var body: some View {
List(makeListItems(for: items), id: \.self) { $0 }
}
}
22. 函数与Combine框架
22.1 创建自定义Publisher
swift复制func countdown(from start: Int) -> AnyPublisher<Int, Never> {
(0...start)
.reversed()
.publisher
.flatMap { value in
Just(value)
.delay(for: .seconds(1), scheduler: DispatchQueue.main)
}
.eraseToAnyPublisher()
}
22.2 操作符函数
swift复制extension Publisher where Output == Int, Failure == Never {
func filterMultiples(of number: Int) -> AnyPublisher<Output, Failure> {
self
.filter { $0 % number == 0 }
.eraseToAnyPublisher()
}
}
let subscription = countdown(from: 10)
.filterMultiples(of: 2)
.sink { print($0) }
// 输出: 10, 8, 6, 4, 2, 0
22.3 错误处理函数
swift复制func fetchWithRetry<T>(
_ attempt: @escaping () -> AnyPublisher<T, Error>,
retries: Int
) -> AnyPublisher<T, Error> {
attempt()
.catch { error -> AnyPublisher<T, Error> in
if retries > 0 {
return fetchWithRetry(attempt, retries: retries - 1)
} else {
return Fail(error: error).eraseToAnyPublisher()
}
}
.eraseToAnyPublisher()
}
23. 函数与Swift宏
23.1 创建函数宏
swift复制@freestanding(expression)
public macro URL(_ string: String) -> URL = #externalMacro(
module: "MyMacros",
type: "URLMacro"
)
// 使用宏
let url = #URL("https://example.com")
23.2 函数调试宏
swift复制@freestanding(declaration)
public macro logFunctionCall<T>(_ message: T) = #externalMacro(
module: "MyMacros",
type: "FunctionCallMacro"
)
func importantFunction() {
#logFunctionCall("importantFunction called")
// 实际代码
}
23.3 函数性能测量宏
swift复制@attached(peer)
public macro measureTime() = #externalMacro(
module: "MyMacros",
type: "MeasureTimeMacro"
)
@measureTime
func timeConsumingOperation() {
// 耗时操作
}
24. 函数与C/Objective-C互操作
24.1 调用C函数
swift复制// 假设有C头文件 math_utils.h
/*
int add_integers(int a, int b);
*/
// Swift中调用
let sum = add_integers(3, 5)
print(sum) // 输出8
24.2 为C提供回调函数
swift复制// C头文件定义
/*
typedef void (*Callback)(const char *message);
void register_callback(Callback callback);
*/
// Swift实现
func callbackHandler(message: UnsafePointer<CChar>?) {
if let message = message {
let swiftString = String(cString: message)
print("Received: \(swiftString)")
}
}
// 注册回调
register_callback(callbackHandler)
24.3 使用@convention(c)定义C兼容函数
swift复制let callback: @convention(c) (Int32, Int32) -> Int32 = { a, b in
return a + b
}
// 可以传递给期望C函数指针的API
25. 函数与Swift性能分析
25.1 使用os_signpost测量性能
swift复制import os.signpost
let log = OSLog(subsystem: "com.example.app", category: "Performance")
func measuredOperation() {
let signpostID = OSSignpostID(log: log)
os_signpost(.begin, log: log,
