2

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?

HangarRash
  • 7,314
  • 5
  • 5
  • 32
  • On a side note, can someone with appropriate privileges please merge the [tag:swift-data] and [tag:swiftdata-apple] tags. – HangarRash Jul 04 '23 at 18:23
  • Hmm, someone must have changed the definition for swift-data since it was first used in 2016 – Joakim Danielson Jul 04 '23 at 20:02
  • @JoakimDanielson Looking at the history of the swift-data tag shows that it was creating June 20, 2023. But you're right. There are questions using the tag since 2016. Maybe it had no tag info until last month. – HangarRash Jul 04 '23 at 20:07
  • Yes I saw that and I don't really understand it. – Joakim Danielson Jul 04 '23 at 20:10
  • @JoakimDanielson Either way, the tags should be merged I think. Most related questions seem to have both but some have one and some have the other. That's going to cause confusion. – HangarRash Jul 04 '23 at 20:11

1 Answers1

1

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.

HangarRash
  • 7,314
  • 5
  • 5
  • 32
  • Interesting, a similar issue was reported [here](https://stackoverflow.com/questions/76545669/swiftdata-missing-argument-for-parameter-1-in-call) for using .init – Joakim Danielson Jul 04 '23 at 20:03
  • @JoakimDanielson Seems related but the error message is quite different. I searched both SwiftData tags with "enum" and the error before posting to avoid a duplicate. – HangarRash Jul 04 '23 at 20:12
  • It's no duplicate but just similar behaviour – Joakim Danielson Jul 04 '23 at 20:13