我正在尝试使用 SwiftUI 对核心数据项进行动态过滤。核心数据实体:项目。属性:日期(Date)、完成(布尔)、名称(字符串)。
提供的代码创建了 3 个 Item 实体实例。列表上方有一个分段控件来更改过滤器值。全部关闭过滤器(doneFilter 设置为 nil)。未完成打开过滤器(将 doneFilter 设置为 false)。
还有一个基于分段控制设置 fetchRequest 的 init。
问题
构建失败并出现错误:
在初始化之前使用的变量“self.fetchRequest”
我的代码有什么问题?
内容视图.swift
import SwiftUI
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
var body: some View {
NavigationView {
VStack {
ListView()
}
.navigationBarTitle("Items")
.navigationBarItems(
leading:
Button(action: {
for number in 1...3 {
let item = Item(context: self.moc)
item.date = Date()
item.name = "Item \(number)"
item.done = false
do {
try self.moc.save()
}catch{
print(error)
}
}
}) {
Text("Add 3 items")
}
)
}
}
}
ListView.swift
import SwiftUI
struct ListView: View {
@Environment(\.managedObjectContext) var moc
var fetchRequest: FetchRequest<Item>
var items: FetchedResults<Item> { fetchRequest.wrappedValue }
@State var doneFilter :Bool? = nil
var doneStatus: Binding<Int> { Binding<Int>(
get: {
if self.doneFilter == false {
return 1
} else {
return 0
}
},
set: {
switch $0 {
case 1:
self.doneFilter = false
default:
self.doneFilter = nil
}
})
}
var body: some View {
List {
Picker(selection: doneStatus, label: Text("Picker")) {
Text("All").tag(0)
Text("Not finished").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.padding()
ForEach(items, id: \.self) {item in
HStack {
Text("\(item.name ?? "default item name")")
Spacer()
Toggle(isOn: Binding<Bool>(
get: { item.done },
set: {
item.done = $0
try? self.moc.save()
})) {
Text("Done")
}
.labelsHidden()
}
}
.onDelete(perform: removeItem)
}
}
func removeItem(at offsets: IndexSet) {
for offset in offsets {
let item = items[offset]
moc.delete(item)
}
try? moc.save()
}
init() {
if let filter = doneFilter {
fetchRequest = FetchRequest<Item>(entity: Item.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Item.name, ascending: true)
], predicate: NSPredicate(format: "done = %d", filter))
} else {
fetchRequest = FetchRequest<Item>(entity: Item.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \Item.name, ascending: true)
])
}
}
}