所以我有这个代码:
struct GameState: Equitable {
let position: SCNVector3
}
extension SCNVector3: @retroactive Equitable {
...
}
我必须在这里进行追溯以消除编译器警告,因为如果 Apple 在 SceneKit 中引入一致性本身就会发生冲突。
我想知道会发生什么?这会导致我现有的应用程序在引入一致性的新操作系统版本上崩溃吗?
此外,当发生这种情况时,我应该如何编写代码才能同时针对旧操作系统和新操作系统进行编译?我不明白如何有可能有条件地遵守基于操作系统版本的协议。
当 Apple 引入
Equatable
一致性时,这将是未定义的行为。来自 Swift Evolution 提案,
既然这个客户端已经声明了这个一致性,如果基金会决定在以后的版本中添加这个一致性,这个客户端将无法构建。然而,在客户端删除其一致性并重建之前,他们的应用程序将表现出未定义的行为,因为不确定该一致性的哪个定义将“获胜”。
考虑到这是 UB,崩溃绝对是你的应用程序可能做的事情之一。
@retroactive
only 使警告静音,不执行任何其他操作。这是你说“我知道我在做什么”的一种方式。
即使您可以“有条件地遵守基于操作系统版本的协议”(您不能),这通常也不是很有用,因为后来添加的一致性可能会做一些与您的应用程序不期望的不同的事情(尽管这是对于
Equatable
来说问题较小),并且会导致意外行为 无论如何。
如果您认为未来
SCNVector3
获得 Equatable
一致性的机会足够高,不要追溯性地遵守它。在其周围创建一个 Equatable
包装器,或手动为 ==
编写 GameState
。
也许将来有办法声明协议的多种一致性并选择在调用站点使用哪种一致性。