我目前有一个ContentView,其中包含一个FetchRequest,我将其存储为变量。如果FetchRequest中的Core Data实体为空,我希望禁用一个菜单项Button(在macOS上)。以下是我的ContentView中的相关代码:
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@SectionedFetchRequest(
sectionIdentifier: \.startDateRelative,
sortDescriptors: [NSSortDescriptor(keyPath: \MyEntity.startDate, ascending: false)],
animation: .default)
var items: SectionedFetchResults<String, MyEntity>
}
在"MyApp"中,我有:
@main
struct MyApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
.commands {
CommandMenu("Database") {
Button("Delete All") {
stuffToDo()
}
.disabled() // This is the problem, what do I put in the ()?
}
}
}
}
问题是,如果我尝试添加.disabled(contentView.items.isEmpty)
,那么我会得到错误Accessing StateObject's object without being installed on a View. This will create a new instance each time.
,它不起作用。
我曾经成功地检查过实体是否为空,但我需要在实体更改时更新,否则它将无法正常工作。
有什么想法吗?
编辑:持久性控制器:
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for _ in 0..<10 {
let newItem = MyEntity(context: viewContext)
newItem.startTime = Date()
}
do {
try viewContext.save()
} catch {
let nsError = error as NSError
print("Unresolved error during save \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "MyApp")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
print("Unresolved data error \(error), \(error.userInfo)")
}
})
container.viewContext.automaticallyMergesChangesFromParent = true
}
}
1条答案
按热度按时间7cwmlq891#
你没有CoreData的问题,你有一个应用程序间的通信问题。你需要改变你的应用程序结构中的状态来启用和禁用CommandMenu。在最简单的世界里,你可以在你的应用程序文件中创建一个State变量,并将其绑定到你的ContentView中的@Binding,然后根据你的获取是否返回任何东西来根据需要简单地改变绑定。但是,我怀疑你有两个视图,因此,另一个稍微复杂一点的方法是允许通过环境更改该值,然后您可以从任何地方触发该更改(具有标准限制),并让其随意禁用或启用CommandMenu。
我首先创建了一个ObservableObject,如果您只需要在视图之间传递一个简单的绑定,并使用它来禁用或启用CommandMenu,那么这个对象就显得多余了:
接下来,我将其添加到App文件中:
还有一个简单的演示ContentView:
通过在环境中传递ObservableObject,您可以控制它,但是更新不会直接影响任何其他视图,除了App结构体。
编辑:
使用. onChange()可以在视图中观察CoreData实体:
您可能需要在开始时禁用CommandMenu,然后在count〉0时启用它。