更新 SwiftData 中的一对一关系

问题描述 投票:0回答:1

我正在尝试构建一个模型,您可以在其中将节目添加到观看列表并查看它们。当您将节目添加到监视列表或查看它时,如果它尚不存在,我将在数据库中创建一个新节目,否则我将检索它并更新它。 我的问题是,当我检索现有节目并向数据库插入新的监视列表项或评论时,它会引发错误“非法尝试在不同上下文中的对象之间建立关系”。据我了解,这是因为观看列表项或评论在节目存在时尚不存在。 但我不知道如何解决这种行为。我每次都尝试创建一个新节目,但是当我通过监视列表项或评论的关系插入它时,它总是创建一个新节目,而不是更新(如果有现有节目)。 这是我的实现,感谢您的帮助

@Model
final class LocalWatchlistItem {
    var addedAt: Date
    var show: LocalShow

    init(show: LocalShow, addedAt: Date = .now) {
        self.show = show
        self.addedAt = addedAt
    }
}
@Model
final class LocalReview {
    var show: LocalShow
    ...

    init(show: LocalShow, ...) {
        self.show = show
        ...
    }
}

@Model
final class LocalShow: Showable {
    @Attribute(.unique) var id: String
    ...
    @Relationship(deleteRule: .cascade, inverse: \LocalWatchlistItem.show) var watchlistItem: LocalWatchlistItem? = nil
    @Relationship(deleteRule: .cascade, inverse: \LocalReview.show) var reviews = [LocalReview]()

    init(
        id: String,
        ...
    ) {
        self.id = id
        ...
    }
func upsertShow(_ show: Show) throws -> LocalShow {
        if let existingShow = try getShow(show.key) {
            existingShow.updatedAt = .now
            existingShow.title = show.title
            ...
            return existingShow
        } else {
            return LocalShow(
                id: show.key,
                createdAt: .now,
                updatedAt: nil,
                title: show.title,
                ...
            )
        }
    }
func addToWatchlist(_ show: Show) throws -> LocalWatchlistItem {
        let upsertedShow = try upsertShow(show)
        let watchlistItem = LocalWatchlistItem(show: upsertedShow)
        database.insert(watchlistItem)
        return watchlistItem
    }
func createReview(for show: Show, rating: Int, comment: String?) throws -> LocalReview {
        let upsertedShow = try upsertShow(show)
        let review = LocalReview(show: upsertedShow, rating: rating, comment: comment)
        database.insert(review)
        return review
    }
swift swift-data
1个回答
0
投票

我找到了一种解决方法,方法是在“LocalWatchlistItem”和“LocalReview”上将“show”设为可选,并按如下方式修改我的函数:

func addToWatchlist(_ show: Show) throws -> LocalWatchlistItem {
        let upsertedShow = try upsertShow(show)
        let watchlistItem = LocalWatchlistItem()
        database.insert(watchlistItem)
        watchlistItem.show = upsertedShow
        return watchlistItem
    }
func createReview(for show: Show, rating: Int, comment: String?) throws -> LocalReview {
        let upsertedShow = try upsertShow(show)
        let review = LocalReview(rating: rating, comment: comment)
        database.insert(review)
        review.show = upsertedShow
        return review
    }

逻辑是根据节目是否存在来插入或更新节目,插入没有任何关系的“watchlistItem”,最后在两个模型都在 modelContext 中时更新关系。通过这种方法,我确保永远不会出现“LocalShow”的重复项,并且不会引发错误“非法尝试在不同上下文中的对象之间建立关系”,因为两个对象都已正确插入。

一般来说,在 SwiftData 中处理任何类型的关系时,我现在建议始终首先插入模型或检索模型,然后更新关系。唯一的缺点是需要对关系进行选择。

© www.soinside.com 2019 - 2024. All rights reserved.