SwiftUI FetchRequest и onReceive вызывают бесконечный цикл - PullRequest
1 голос
/ 06 октября 2019

У меня есть @FetchRequest для NSManagedObject в swiftUI. Я пытаюсь изменить заголовок первого элемента в основных данных, когда используется переключатель, вызывая onReceive. Это не работает , если полученные результаты используются в MainVC. Чтобы продемонстрировать это, заголовок кнопок навигации - это количество элементов в выбранном результате. В результате создается бесконечный цикл в методе ContentView onRecieve. Если кнопка навигации содержит обычный текст, а не использует что-либо из FetchedResults, тогда петли нет, и все работает как положено. Как вызывается этот цикл, и есть ли лучший способ переключения определенного основного элемента данных?

import SwiftUI
import CoreData

final class ContentVCModel : ObservableObject{
    @Published var newToDoItem = String()
    @Published var shouldTurnOn = false

    func createNewToDoItem(){
        let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

        let toDoItem = ToDoItem(context: moc)
        toDoItem.title = self.newToDoItem
        toDoItem.createdAt = Date()
        toDoItem.cost = Cost(main: "$\(Int.random(in: 1...99))", tax: "$\(Int.random(in: 1...9))")
        toDoItem.isOn = false

        ToDoItem.save()
        self.newToDoItem = ""
    }
}

struct ContentView: View {
    @ObservedObject var model = ContentVCModel()
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(fetchRequest: ToDoItem.getAllToDoItems()) var toDoItems : FetchedResults<ToDoItem>

    var body: some View {
        List{
            Section(header : Text("Whats next?")){
                Toggle("Toggle Test", isOn: $model.shouldTurnOn)
                    .onReceive(model.$shouldTurnOn) { (newValue) in
                        self.toDoItems.first?.title = "\(Int.random(in: 23...3423))"
                        //infitine loop
                }
                HStack{
                    TextField("New Item", text: $model.newToDoItem)
                        Button(action: {
                            self.model.createNewToDoItem()
                        }){
                            Image(systemName: "plus.circle.fill")
                                .foregroundColor(self.model.newToDoItem.isEmpty ? .gray : .green)
                                .imageScale(.large)
                        }.disabled(self.model.newToDoItem.isEmpty)
                    }
                }.font(.headline)
                Section(header: Text("To Do's")){
                    ForEach(toDoItems) { toDoItem in
                        ToDoItemView(title: toDoItem.title, createdAt: toDoItem.createdAt.description, cost: toDoItem.cost, isOn: true)
                    }.onDelete { (indexSet) in
                        let deleteItem = self.toDoItems[indexSet.first!]
                        self.managedObjectContext.delete(deleteItem)
                        ToDoItem.save()
                    }
                }
            }
            .navigationBarTitle(Text("My List"))
            .navigationBarItems(trailing: EditButton())
        }
}


struct MainVC : View {
    @FetchRequest(fetchRequest: ToDoItem.getAllToDoItems()) var toDoItems : FetchedResults<ToDoItem>

    var body: some View {
        NavigationView{
            NavigationLink(destination: ContentView()) {
                Text("\(toDoItems.count)") //Using toDoItems causes this to repeat ex: "\(toDoItems.count)"
            }
        }
    }
}
...