Swift 3/4中Any类型如何实现respondsToSelector:@selector(charValue)等价功能?
Swift 3/4中处理Any类型的
respondsToSelector等价方案 我明白你搜了好久都没找到合适的解决办法,确实Swift里Any类型不像AnyObject那样直接有responds(to:)方法,这里给你几个针对Any类型、对应OC中[(id)object respondsToSelector:@selector(charValue)]的可行方案:
方案一:桥接AnyObject + 类型兜底判断
Swift里的基础值类型(比如Int、Float)会自动桥接到OC的NSNumber,我们可以先尝试把Any转成AnyObject,再用OC的运行时方法判断,同时对无法桥接的Swift原生类型做兜底检查:
func canPerformCharValue(_ object: Any) -> Bool { // 先尝试转成AnyObject,调用OC的responds(to:) if let obj = object as? AnyObject { return obj.responds(to: #selector(getter: NSNumber.charValue)) } // 对Swift原生数值类型直接判断(它们本身可以转换为CChar) switch object { case is Int, is UInt, is Float, is Double, is CChar: return true default: return false } }
这个方案兼顾了OC对象和Swift原生值类型,是比较稳妥的过渡方案。
方案二:Swift风格的协议扩展(推荐)
如果想摆脱OC运行时的依赖,用Swift的类型安全特性来实现,可以定义一个协议,让所有支持charValue的类型遵守:
// 定义协议 protocol CharValueConvertible { func charValue() -> CChar } // 让Swift原生数值类型遵守协议 extension Int: CharValueConvertible { func charValue() -> CChar { return CChar(self) } } extension UInt: CharValueConvertible { func charValue() -> CChar { return CChar(self) } } extension Float: CharValueConvertible { func charValue() -> CChar { return CChar(self) } } // OC的NSNumber本身就有charValue方法,直接遵守协议 extension NSNumber: CharValueConvertible {} // 判断对象是否支持charValue func canPerformCharValue(_ object: Any) -> Bool { return object is CharValueConvertible } // 调用示例 if let convertible = object as? CharValueConvertible { let result = convertible.charValue() // 执行后续操作 }
这种方式完全符合Swift的设计理念,类型安全且扩展性强,你可以随时给其他类型添加协议扩展。
方案三:直接使用OC运行时函数(不推荐,仅兼容场景用)
如果必须完全复刻OC的写法,可以用Swift的类型转换配合OC运行时,但要注意这仅适用于能桥接成OC对象的类型:
import Foundation func respondsToCharValue(_ object: Any) -> Bool { guard let obj = object as? AnyObject else { return false } let selector = #selector(getter: NSNumber.charValue) return obj.responds(to: selector) }
注意:如果传入的
Any是Swift纯自定义值类型(比如自定义结构体),转成AnyObject会触发自动桥接,但如果是无法桥接的类型,这个方法会返回false,甚至可能引发崩溃,所以务必谨慎使用。
内容的提问来源于stack exchange,提问作者lreddy
相关产品推荐
相关产品推荐

