SwiftUI-初始化前使用的变量'self.fetchRequest'

时间:2020-06-29 15:18:36

标签: ios swift initialization swiftui fetchrequest

我正在尝试使用SwiftUI对Core Data项目进行动态过滤。 核心数据实体:项目。属性:日期(日期),完成(布尔值),名称(字符串)。

提供的代码创建3个Item实体的实例。列表上方是一个分段控件,用于更改过滤器值。 全部关闭过滤器(doneFilter设置为nil)。未完成打开过滤器(将doneFilter设置为false)。

还有一个用于根据分段控件设置fetchRequest的初始化程序。

问题

构建失败并显示错误:

在初始化之前使用的变量'self.fetchRequest'

我的代码有什么问题?

ContentView.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)
            ])
        }
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个类似的代码。主要区别在于,分段控件已移至ContentView,并通过ListView中的参数将doneFilter传递给ListView(过滤器:doneFilter)。 ListView中的初始化代码也有一些更改。

ContentView.swift

import SwiftUI

struct ContentView: View {
    
    @Environment(\.managedObjectContext) var moc
    
    @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 {
        
        NavigationView {
            List {
                
                Picker(selection: doneStatus, label: Text("Picker")) {
                    Text("All").tag(0)
                    Text("Not finished").tag(1)
                }
                .pickerStyle(SegmentedPickerStyle())
                .padding()
                
                ListView(filter: doneFilter)
            }
            .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 }
    
    var body: some View {
        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(filter: Bool?) {
        if let filter = filter {
        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)
            ])
        }
    }
}

但是我仍然不知道如何使第一版工作。一个分段控件和init都在ListView上。