如何修复@Sendable闭包中捕获非Sendable类型ISO8601DateFormatter的警告?
修复ISO8601DateFormatter在@Sendable闭包中的捕获警告
问题代码
let dateFormatter = ISO8601DateFormatter() dateFormatter.formatOptions.insert(.withFractionalSeconds) decoder.dateDecodingStrategy = .custom({ decoder in let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) return dateFormatter.date(from: dateStr) ?? Date() //warning })
出现警告:Capture of 'dateFormatter' with non-sendable type 'ISO8601DateFormatter' in a @Sendable closure
修复方案
方案一:将dateFormatter标记为Sendable(iOS16+/macOS13+适用)
从iOS16和macOS13开始,ISO8601DateFormatter原生符合Sendable协议,直接声明类型即可消除警告:
let dateFormatter: ISO8601DateFormatter & Sendable = ISO8601DateFormatter() dateFormatter.formatOptions.insert(.withFractionalSeconds) decoder.dateDecodingStrategy = .custom({ decoder in let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) return dateFormatter.date(from: dateStr) ?? Date() })
如果是低版本系统,可使用@unchecked Sendable手动标记(苹果文档明确ISO8601DateFormatter是线程安全的,可安全使用):
let dateFormatter = ISO8601DateFormatter() as @unchecked Sendable dateFormatter.formatOptions.insert(.withFractionalSeconds) decoder.dateDecodingStrategy = .custom({ @Sendable [dateFormatter] decoder in let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) return dateFormatter.date(from: dateStr) ?? Date() })
方案二:在闭包内部创建dateFormatter
直接在闭包内初始化ISO8601DateFormatter,避免外部变量捕获:
decoder.dateDecodingStrategy = .custom({ decoder in let dateFormatter = ISO8601DateFormatter() dateFormatter.formatOptions.insert(.withFractionalSeconds) let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) return dateFormatter.date(from: dateStr) ?? Date() })
注意:此方法每次调用闭包都会创建新的格式化器,频繁解码时可能存在性能损耗。
方案三:使用静态常量复用格式化器(推荐)
利用静态常量的懒加载和线程安全特性,既复用格式化器,又避免捕获问题:
// 在类/结构体内部定义静态格式化器 private static let dateFormatter: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions.insert(.withFractionalSeconds) return formatter }() // 解码时使用静态格式化器 decoder.dateDecodingStrategy = .custom({ decoder in let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) return Self.dateFormatter.date(from: dateStr) ?? Date() })
内容的提问来源于stack exchange,提问作者erotsppa
相关产品推荐
相关产品推荐

