SwiftData中枚举属性设默认值引发编译错误,该如何修复?
SwiftData枚举属性默认值编译错误的修复方案
说明:
- 本问题最初发布于Xcode 15测试版期间。在Xcode 15正式版中,编译器给出的错误提示更为清晰:
A default value requires a fully qualified domain named value
原始问题:
我把问题简化为一个带枚举属性的简单模型类,尝试给这个属性设置默认值时,代码无法编译:
enum SomeEnum: Hashable, Codable { case one case two } @Model class SomeClass { var value: SomeEnum = .two init() { } }
编译后会出现如下错误:
type 'Any?' has no member 'two'
查看详细日志能看到更多信息:
@__swiftmacro_8Sample39SomeClass5ModelfMm_.swift:15:34: error: type 'Any?' has no member 'two' ("value", \SomeClass.value, .two, nil) ~^~~ /.../Sample.swift:117:1: note: in expansion of macro 'Model' here class SomeClass { ^~~~~~~~~~~~~~~~~ /.../Sample.swift:117:1: note: in expansion of macro 'Model' here class SomeClass { ^~~~~~~~~~~~~~~~~
右键点击@Model选择“Expand Macro”(展开宏)后,能看到宏生成的代码:
@Model class SomeClass { var value: SomeEnum = .two init() { } @Transient private var _$backingData: any SwiftData.BackingData<SomeClass> = SwiftData.DefaultBackingData(for: SomeClass.self) public var backingData: any SwiftData.BackingData<SomeClass> { get { _$backingData } set { _$backingData = newValue } } static func schemaMetadata() -> [(String, AnyKeyPath, Any?, Any?)] { return [ ("value", \SomeClass.value, .two, nil) // <-- 错误位置 ] } required init(backingData: any SwiftData.BackingData<SomeClass>) { self.backingData = backingData } @Transient private let _$observationRegistrar = Observation.ObservationRegistrar() }
错误明显来自schemaMetadata()函数内部。
修复方法
问题根源是SwiftData宏展开时,无法正确推断简写形式.two的枚举类型。解决办法很简单,使用完全限定的枚举值指定默认值,把.two替换成SomeEnum.two即可:
修改后的代码:
enum SomeEnum: Hashable, Codable { case one case two } @Model class SomeClass { var value: SomeEnum = SomeEnum.two init() { } }
这样修改后,宏生成的schemaMetadata()函数能正确识别枚举值的类型,编译错误就会消失。原因是宏生成的代码里,默认值被放在Any?类型的位置,简写枚举值无法被编译器正确解析,而完全限定名能明确告知编译器具体的枚举类型和对应值。
内容的提问来源于stack exchange,提问作者HangarRash
相关产品推荐
相关产品推荐

