HangarRash
HangarRash

Reputation: 15012

SwiftData compiler error on enum property with default value

Note: - This question was originally posted while Xcode 15 was in beta. With the final release of Xcode 15, the compiler gives a much clearer error stating:

A default value requires a fully qualified domain named value


The original question:

I've narrowed down this issue to a simple model class with one property with a enum type. If I attempt to give the property a default value, the code won't compile any more:

enum SomeEnum: Hashable, Codable {
    case one
    case two
}

@Model
class SomeClass {
    var value: SomeEnum = .two

    init() {
    }
}

This results in the error:

type 'Any?' has no member 'two'

If you dig into the actual log, you can see a bit more info:

@__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 {
^~~~~~~~~~~~~~~~~

If you right click on @Model and select "Expand Macro", you see:

@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) // <-- Error here
      ]
    }
    
    required init(backingData: any SwiftData.BackingData<SomeClass>) {
      self.backingData = backingData
    }
    
    @Transient
    private let _$observationRegistrar = Observation.ObservationRegistrar()

}

The error appears to be coming from inside the schemaMetadata() function.

What's the fix for this?

Upvotes: 10

Views: 2284

Answers (1)

HangarRash
HangarRash

Reputation: 15012

Note: This answer applies to both Xcode 15 beta and the release version of Xcode 15. Of course the updated compiler error in the release version of Xcode 15 makes this answer much more obvious than it was during the beta.


Turns out this can be resolved by changing the line:

var value: SomeEnum = .two

to:

var value: SomeEnum = SomeEnum.two

or

var value = SomeEnum.two

Either of those two changes results in the schemaMetadata() line being updated to:

("value", \SomeClass.value, SomeEnum.two, nil)

which makes the compiler happy.

Or you can move the initial value from the property and put it in the init:

var value: SomeEnum

init(value: SomeEnum = .two) {
    self.value = value
}

This seems like a bug in the SwiftData macros that it can't properly expand .two to SomeEnum.two when generating the schemaMetadata() function.

Upvotes: 18

Related Questions