2

This code worked perfectly fine with Xcode 15 beta 2.

@Model
final class Room {
    var name: String = ""
    @Relationship var plants: [Plant]?
    
    init(name: String, plants: [Plant] = []) {
        self.name = name
    }
}

Right now, with Xcode 15 beta 6, the property declaration lines that have initial value throw this:

var name: String = "" // Variable 'self._$backingData' used before being initialized

Giving the initial value within the initialiser does not solve the issue, the modelContainer won't get initialised correctly and the app will crash.

CloudKit integration requires properties to have either initial values, or being the optional type. I'd like to avoid declaring optional values when not necessary.

Is this a bug? Or expected behaviour? Thanks for all the help.

Jakub Gawecki
  • 801
  • 2
  • 6
  • 14

1 Answers1

2

Starting from Xcode 15.0 beta 6, there's a bug where projects created prior to Xcode 15.0 beta 6 don't work with the SwiftData macro. You might either need to create a new project or try without the macro as shown in the code below.

final class Room: PersistentModel, Observable {
    static func schemaMetadata() -> [(String, AnyKeyPath, Any?, Any?)] {
        [
            ("name", \Room.name, nil, nil),
            ("plants", \Room.plants, nil, Schema.Relationship())
        ]
    }
    
    var name: String {
        get {
            observationRegistrar.access(self, keyPath: \.name)
            return persistentBackingData.getValue(forKey: \.name)
        }
        set {
            observationRegistrar.withMutation(of: self, keyPath: \.name) {
                observationRegistrar.willSet(self, keyPath: \.name)
                persistentBackingData.setValue(forKey: \.name, to: newValue)
                observationRegistrar.didSet(self, keyPath: \.name)
            }
        }
    }
    
    var plants: [Plant]? {
        get {
            observationRegistrar.access(self, keyPath: \.plants)
            return persistentBackingData.getValue(forKey: \.plants)
        }
        set {
            observationRegistrar.withMutation(of: self, keyPath: \.plants) {
                observationRegistrar.willSet(self, keyPath: \.plants)
                persistentBackingData.setValue(forKey: \.plants, to: newValue)
                observationRegistrar.didSet(self, keyPath: \.plants)
            }
        }
    }
    
    var persistentBackingData: any BackingData<Room>

    private let observationRegistrar: ObservationRegistrar = .init()
    
    init(name: String = "", plants: [Plant] = []) {
        self.persistentBackingData = Room.createBackingData()
        self.name = name
        self.plants = plants
    }
    
    init(backingData: any BackingData<Room>) {
        self.persistentBackingData = backingData
    }
}
Jinwoo Kim
  • 440
  • 4
  • 7