如何判断两个Swift函数是否为同一引用?
Swift中如何比较函数引用是否相同?
问题场景
我定义了一个接收函数作为参数的方法:
mutating func updateAccessCaches(by areInIncreasingOrder: (NumberedFile, NumberedFile) -> Bool = sortByOldIDPrio) { ... }
尝试直接比较传入的函数和默认函数是否为同一引用:
if areInIncreasingOrder == sortByOldIDPrio { ... }
但触发报错:
Binary operator '==' cannot be applied to operands of type '(DSRenamer.NumberedFile, DSRenamer.NumberedFile) -> Swift.Bool' and '(DSRenamer.NumberedFile, DSRenamer.NumberedFile) -> Swift.Bool'
不想通过调用函数比较结果的方式判断,想实现类似C语言中直接对比函数引用的效果。
解决方案
Swift本身不支持直接比较函数类型的相等性——因为函数类型可能包含捕获上下文的闭包,无法简单判断引用是否一致。但针对无上下文捕获的函数(比如顶层函数、类型静态方法),可以用以下两种方式实现:
1. 通过内存地址比较(仅适用于无捕获的函数)
利用unsafeBitCast将函数转换为内存指针,直接对比地址是否相同:
// 将函数转换为原始指针 let defaultFuncPtr = unsafeBitCast(sortByOldIDPrio, to: UnsafeRawPointer.self) let inputFuncPtr = unsafeBitCast(areInIncreasingOrder, to: UnsafeRawPointer.self) if defaultFuncPtr == inputFuncPtr { // 两个函数是同一引用 }
⚠️ 注意:这种方法绝对不能用在捕获了变量的闭包上,会导致未定义行为,仅适用于无上下文的纯函数。
2. 封装为枚举/自定义类型(安全通用方案)
如果需要更安全的逻辑区分,可以把排序策略封装成枚举,用枚举值代替直接传递函数:
enum SortStrategy { // 默认排序策略 case oldIDPrio // 自定义排序闭包 case custom((NumberedFile, NumberedFile) -> Bool) // 执行排序比较的方法 func compare(_ a: NumberedFile, _ b: NumberedFile) -> Bool { switch self { case .oldIDPrio: return sortByOldIDPrio(a, b) case .custom(let comparator): return comparator(a, b) } } }
然后修改原方法的参数类型:
mutating func updateAccessCaches(by strategy: SortStrategy = .oldIDPrio) { if strategy == .oldIDPrio { // 匹配默认策略的专属逻辑 } // 使用排序策略时调用:strategy.compare(fileA, fileB) }
这种方式完全规避了函数引用比较的问题,同时逻辑更清晰,也支持自定义排序需求。
内容的提问来源于stack exchange,提问作者Peter71
相关产品推荐
相关产品推荐

