如何让CMTime在所有iOS版本中遵循Hashable协议?
全iOS版本兼容CMTime/CMTimeRange的Hashable一致性解决方案
问题背景
Xcode 14中,苹果仅为iOS 16及以上版本的CMTime和CMTimeRange添加了Hashable协议一致性。若项目中存在大量包含CMTime的Hashable结构体,且需要兼容低版本iOS,会遇到编译报错或兼容性问题。
方案一:带版本控制的Hashable扩展(推荐)
你提到的实现hashValue的方案是安全可行的,只需补充版本标记和完整的协议实现即可解决编译问题,且无需修改现有业务代码。
完整代码实现
import CoreMedia // 为CMTime添加Hashable兼容,覆盖iOS 16以下版本 @available(iOS, introduced: 8.0, deprecated: 16.0, message: "iOS 16+ 已提供原生Hashable一致性") extension CMTime: Hashable, Equatable { public static func == (lhs: CMTime, rhs: CMTime) -> Bool { // 复用系统的相等判断逻辑 return CMTimeEqualToTime(lhs, rhs) } public func hash(into hasher: inout Hasher) { // 根据CMTime核心字段生成哈希值,对齐iOS 16+原生实现逻辑 hasher.combine(value) hasher.combine(timescale) hasher.combine(flags) hasher.combine(epoch) } @available(iOS, deprecated: 16.0, message: "推荐使用hash(into:)替代") public var hashValue: Int { var hasher = Hasher() hash(into: &hasher) return hasher.finalize() } } // 同理处理CMTimeRange @available(iOS, introduced: 8.0, deprecated: 16.0, message: "iOS 16+ 已提供原生Hashable一致性") extension CMTimeRange: Hashable, Equatable { public static func == (lhs: CMTimeRange, rhs: CMTimeRange) -> Bool { return CMTimeRangeEqualToTimeRange(lhs, rhs) } public func hash(into hasher: inout Hasher) { hasher.combine(start) hasher.combine(duration) } @available(iOS, deprecated: 16.0, message: "推荐使用hash(into:)替代") public var hashValue: Int { var hasher = Hasher() hash(into: &hasher) return hasher.finalize() } }
方案安全性说明
- hashValue弃用不影响功能:
hashValue的弃用只是Swift API演进的提示,并非功能移除,在低版本iOS中依然能正常工作。 - 哈希一致性保障:
hashValue完全基于hash(into:)生成,保证同一CMTime在不同版本系统中生成的哈希值一致。 - 版本隔离避免冲突:通过
@available标记,iOS 16+系统会优先使用原生的Hashable实现,我们的扩展仅在低版本生效,不会产生冲突。 - 编译报错解决:给
hashValue添加弃用标记后,编译器会认可其可用性覆盖范围,不再抛出“requires 'hashValue' to be available”的错误。
方案二:封装Hashable容器(不推荐)
你提到的封装Hashed结构体的方案虽然可行,但需要修改所有包含CMTime的Hashable结构体的hash(into:)实现,改动范围大、维护成本高,仅在无法使用方案一的极端场景下考虑。
内容的提问来源于stack exchange,提问作者Guy Niv
相关产品推荐
相关产品推荐

