NSFetchRequest返回错误的.c​​ount值

问题描述

在使用SwiftUI作为界面的应用中,我有一个执行动作的按钮:

func getBooksCountNumber() -> Int {
    var countResult = 0
    let booksFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "Book")
    
    do {
        let booksFetch = try self.persistentContainer.viewContext.fetch(booksFetch) as! [Book]
        countResult = booksFetch.count
        print("countResult is \(countResult)")
    } catch {
        fatalError("Failed to fetch: \(error)")
    }

    return countResult
}

当我在应用程序中删除行时,我使用moc.delete(book)try? moc.save()。我使用icloud.developer.apple.com上的界面看到删除的行消失了。例如,如果从3条记录中删除1条,我在countResult中仍然得到3条,而不是2条。任何帮助都是值得的。

解决方法

SwiftUI依靠数据无效来强制重新加载View

因此,您需要考虑如何使View依赖于数据countResult(例如)。

如果您使用的是SwiftUI,建议您考虑使用@FetchRequest属性包装器来获取数据集...

@FetchRequest(entity: Book.entity(),sortDescriptors: []
) var books: FetchedResults<Book>

请注意:sortDescriptors:参数是必需的,因此,如果您不想对FetchedResults进行排序,则可以包含一个空数组[]

然后使用与该包装器关联的属性将数据输入到您的视图中...

struct YourView: View {
    // @FetchRequest here
    var body: some View {
        ...
        Text("Book count = \(books.count)")
        ...
    }
}

这样,您甚至不需要按按钮即可确定计数,因为每次在Text实体中添加或删除书籍时,Book视图都会更新。 / p>

以SwiftUI方式编写,随着数据的更改,Text视图组件将失效,视图struct将被强制重绘。

如果您希望将按钮保留在视图中,则可以执行以下操作...

    var body: some View {
        ...
        Button(action: {
            // code to perform your action here...
        }) {
            Text("You have \(books.count) books")
        }
        ...
    }

按钮的标签上包含书籍数量(按钮执行其他操作)。