最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ios - SwiftData Many-To-Many Relationship: Failed to fulfill link PendingRelationshipLink - Stack Overflow

programmeradmin0浏览0评论

I got two models here:

Two Models, with Many-To-Many Relationship

@Model
    final class PresetParams: Identifiable {
        @Attribute(.unique) var id: UUID = UUID()
        
        var positionX: Float = 0.0
        var positionY: Float = 0.0
        var positionZ: Float = 0.0
        
        var volume: Float = 1.0
        
        @Relationship(deleteRule: .nullify, inverse: \Preset.presetAudioParams)
        var preset = [Preset]()
        
        init(position: SIMD3<Float>, volume: Float) {
            self.positionX = position.x
            self.positionY = position.y
            self.positionZ = position.z
            self.volume = volume
            self.preset = []
        }
        
        var position: SIMD3<Float> {
            get {
                return SIMD3<Float>(x: positionX, y: positionY, z: positionZ)
            }
            set {
                positionX = newValue.x
                positionY = newValue.y
                positionZ = newValue.z
            }
        }
    }
    
    @Model
    final class Preset: Identifiable {
        @Attribute(.unique) var id: UUID = UUID()
        var presetName: String
        var presetDesc: String?
        
        var presetAudioParams = [PresetParams]()  // Many-To-Many Relationship.
        
        init(presetName: String, presetDesc: String? = nil) {
            self.presetName = presetName
            self.presetDesc = presetDesc
            self.presetAudioParams = []
        }
    }

To be honest, I don't fully understand how the @Relationship thing works properly in a Many-To-Many relationship situation. Some tutorials suggest that it's required on the "One" side of an One-To-Many Relationship, while the "Many" side doesn't need it.

And then there is an ObservableObject called "ModelActors" to manage all ModelActors, ModelContainer, etc.

ModelActors, ModelContainer...

class ModelActors: ObservableObject {
    static let shared: ModelActors = ModelActors()
    
    let sharedModelContainer: ModelContainer
    
    private init() {
        var schema = Schema([
            // ...
            Preset.self,
            PresetParams.self,
            // ...
        ])
        
        do {
            sharedModelContainer = try ModelContainer(for: schema, migrationPlan: MigrationPlan.self)
        } catch {
            fatalError("Could not create ModelContainer: \(error.localizedDescription)")
        }
    }
    
}

And there is a migrationPlan:

MigrationPlan

// MARK: V102
// typealias ...

// MARK: V101
typealias Preset = AppSchemaV101.Preset
typealias PresetParams = AppSchemaV101.PresetParams

// MARK: V100
// typealias ...

enum MigrationPlan: SchemaMigrationPlan {
    static var schemas: [VersionedSchema.Type] {
        [
            AppSchemaV100.self,
            AppSchemaV101.self,
            AppSchemaV102.self,
        ]
    }

    static var stages: [MigrationStage] {
        [AppMigrateV100toV101, AppMigrateV101toV102]
    }
    
    static let AppMigrateV100toV101 = MigrationStage.lightweight(fromVersion: AppSchemaV100.self, toVersion: AppSchemaV101.self)
    
    static let AppMigrateV101toV102 = MigrationStage.lightweight(fromVersion: AppSchemaV101.self, toVersion: AppSchemaV102.self)

}

// MARK: Here is the AppSchemaV101

enum AppSchemaV101: VersionedSchema {
    static var versionIdentifier: Schema.Version = Schema.Version(1, 0, 1)
    
    static var models: [any PersistentModel.Type] {
        return [  // ...
                Preset.self,
                PresetParams.self
        ]
    }
}

Fails on iOS 18.3.x: "Failed to fulfill link PendingRelationshipLink"

So I expected the SwiftData subsystem to work correctly with version control. A good news is that on `iOS 18.1 `it does work. But it fails on iOS 18.3.x with a fatal Error:

"SwiftData/SchemaCoreData.swift:581: Fatal error: Failed to fulfill link PendingRelationshipLink(relationshipDescription: (<NSRelationshipDescription: 0x30377fe80>), name preset, isOptional 0, isTransient 0, entity PresetParams, renamingIdentifier preset, validation predicates (), warnings (), versionHashModifier (null)userInfo {}, destination entity Preset, inverseRelationship (null), minCount 0, maxCount 0, isOrdered 0, deleteRule 1, destinationEntityName: "Preset", inverseRelationshipName: Optional("presetAudioParams")), couldn't find inverse relationship 'Preset.presetAudioParams' in model"

Fails on iOS 17.5: Another Error

I tested it on iOS 17.5 and found another issue: Accessing or mutating the "PresetAudioParams" property causes the SwiftData Macro Codes to crash, affecting both Getter and Setter. It fails with an error "EXC_BREAKPOINT (code=1, subcode=0x1cc1698ec)"

Tweaking the @Relationship marker and ModelContainer settings didn't fix the problem.

发布评论

评论列表(0)

  1. 暂无评论