Swift中NSMutableArray在不同iOS版本下的行为差异原因
问题与解答
代码示例
protocol TestProtocol { } struct TestStruct: TestProtocol { } let arr = NSMutableArray() let testStruct = TestStruct() arr.add(testStruct) print("\(arr[0] is TestProtocol)")
现象差异
- iOS 14.0及以上版本:输出
true - iOS 13版本:输出
false
原因分析
这是Swift与Objective-C桥接逻辑在iOS 14上的修复导致的差异:
- 值类型的Objective-C包装:Swift结构体属于值类型,当存入
NSMutableArray这类Objective-C容器时,会被自动包装成__SwiftValue对象——这是Swift为了让值类型兼容Objective-C对象体系设计的包装类型。 - iOS 13的局限:在iOS 13及更早版本中,Objective-C运行时无法穿透
__SwiftValue包装,去识别内部值类型所遵循的协议。执行arr[0] is TestProtocol时,实际检查的是__SwiftValue对象本身是否遵循TestProtocol(它并不遵循),因此返回false。 - iOS 14的修复:iOS 14起,苹果优化了桥接逻辑,让协议类型检查能够穿透
__SwiftValue包装,直接判断内部的Swift值类型是否符合协议要求,因此此时会返回正确的true。
额外提示:如果使用Swift原生容器(比如Array<TestProtocol>)存储,就不会出现这种跨版本差异,因为原生容器无需Objective-C桥接,能直接识别Swift值类型的协议一致性。
内容的提问来源于stack exchange,提问作者Dmitry Suvorov
相关产品推荐
相关产品推荐

