SwiftUI中的视图在模型更改时不会更新(使用SwiftData)

nvbavucw  于 2023-06-28  发布在  Swift
关注(0)|答案(2)|浏览(159)

我在modelContext中插入了一个新项(在单个Deck上),视图应该自动更新,但它没有。仅当我从单个Deck视图导航回Deck视图列表时,它才会刷新。我不知道我在这里做错了什么。

  • 当我从牌组中删除一张牌时,它也不起作用
    • 这看起来像是我在传递一个值而不是一个引用。但我找不到地点**

我的视图结构看起来像这样:

  • 甲板视图(甲板列表)
  • 牌组视图(牌组中的牌列表-我正在从该视图添加新牌)
  • 卡片视图(单卡)
private func addCard() {
  let newCard = Card(
    front: front,
    deck: cardModel.deck!
  )
            
  withAnimation {
    modelContext.insert(newCard)
  }
}

CardModel存储卡片组(在尝试将新的Card插入上下文之前,我确保卡片组不为nil):

@Observable
final class CardModel {
    var deck: Deck? = nil

    public func showAddSheet(deck: Deck) -> Void {
        self.deck = deck
    }
}

甲板型号:

@Model
final class Deck {
    @Relationship(.cascade)
    var cards: [Card]? = [Card]()
    var name: String = ""
    
    init(name: String) {
        self.cards = [Card]()
        self.name = name
    }
}

卡片型号:

@Model
final class Card {
    @Relationship(inverse: \Deck.cards)
    var deck: Deck? = nil
    var front: String = ""
    
    init(front: String, deck: Deck) {
        self.deck = deck
        self.front = front
    }
}

路由器类别:

enum Path: Hashable {
    case decks
    case deck(Deck)
}

@Observable
final class RouterModel {
    var path: [Path] = [Path]()
}

甲板视图:

struct DecksView: View {
    @Query() var decks: [Deck]

    var body: some View {
        List {
            NavigationStack(path: $routerModel.path) {
                ForEach(decks, id: \.self) { deck in
                    NavigationLink(value: Path.deck(deck)) {
                        Text(deck.name)
                    }
                }
            }
        }
        .navigationDestination(for: Path.self, destination: { path in
                switch path {
                    case .decks:
                        DecksView()
                    case let .deck(deck):
                        DeckView(deck: deck)
                    case let .card(card):
                        CardView(card: card)
                }
            })
    }
}

甲板视图:

struct DeckView: View {
    var deck: Deck
    
    var body: some View {
        List {
            ForEach(cards) { card in
                VStack {
                    Text(card.front)
                }
            }
        }
    }
}
gmxoilav

gmxoilav1#

SwiftUI中的视图是一种“静态”的,并且在视图渲染周期中由系统多次构造,销毁和重建。
为了在这个过程中非常快速,所有SwiftUI视图都是struct,根据定义,Swift中的结构体总是通过复制传递其值。在设计SwiftUI应用程序时请记住这一点。
在您的例子中,DeckView没有任何线索表明它是更大架构的一部分,并且deck属性可能会更改。只有DecksView具有此上下文。一旦它导航到DeckView子视图,视图就不会接收更新,并且DecksView沿着属性可能会在它离开前台时立即被销毁。
一个很好的替代方案是DeckView拥有自己的@Query,您只需将id传递给其构造函数,然后它自己查询。这样,DeckView正在使用的数据上触发的任何更改都将触发具有更新数据的新渲染。

uyto3xhc

uyto3xhc2#

您缺少卡片的Query,但SwiftData当前不支持查询关系,即因此,您需要使用Core Data @FetchRequest和 predicate 来表示关系。同时运行Core Data和Swift Data是相当复杂的,所以您可能只使用Core Data会更好,因为可能会缺少您需要的其他功能。

相关问题