SwiftUI核心数据不会刷新“一对多”消息。关系正确,列表未刷新 [英] SwiftUI Core Data does not refresh "one to many" relations properly and lists are not refreshed

查看:177
本文介绍了SwiftUI核心数据不会刷新“一对多”消息。关系正确,列表未刷新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚我可能做错了什么(或者,当然是对关系,获取和所有东西的误解)。



搜索,当我阅读该问题的标题时,希望该问题对我有帮助,但是我错了:




没有与所选客户相关的位置:



所以,我在新项目上添加了:



该数字的位置仍为零,但应为1:




解决方案

iOS的一个巨大惊喜:核心数据控制器仅在基本字段上起作用。


令人难以置信的是,CoreData 不会 根据关系进行更新。


仅基本字段(整数,字符串等)。


您可以看到许多有关此奇怪问题的质量检查和文章,例如:


关系未更新的NSFetchedResultsController


它是正好。


已经有很多尝试来解决这种奇怪的情况。没有真正的解决方案。 NSFetchedResultsController就是它 -它仅适用于基本字段(字符串,整数等)。


不幸的是,这种情况。


注意:如果我对这里的问题有误解,对不起。但是我相信这就是问题所在。


I'm trying to figure out what I can possibly be doing wrong (or, of course, misunderstood about relationships, fetches and all).

In a first search, when I read the question's title, I hoped this question could help me, but I was wrong:

SwiftUI TabView with List not refreshing after objected deleted from / added to Core Data

Anyway...

In my app, when I touch a customer item, the detail view is shown properly with its data. If I change any attribute and go back to the first view, its updated correctly.

My problems start when I add a new location or delete one of the existing ones. When I go back to first view, the number of consumer's existing locations is not updated. When I close and reopen the app, all the data is correctly show.

As I said, my Core Data's model has 2 entities, like this:

Entity: Customer id: String name: String locationList: [Location] (to-many (Location), cascade)

Entity: Location id: String addess: String fromCustomer: Customer (to-One (Customer), nullify)

This is the view witch shows the Customers list:


struct CustomerList: View {

    @Environment(\.managedObjectContext) var moc

    @FetchRequest(
        entity: Customer.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Customer.name, ascending: true),
        ]
    ) var customerList: FetchedResults<Customer>

    var body: some View {

        VStack{
            CustomerArea
        }
        .navigationBarTitle(Text("Customers"), displayMode: .inline)
        .navigationBarItems(leading: btnCreate, trailing: btnNew)

    }

    var CustomerArea: some View {

        List{

            ForEach(customerList, id: \.id) { customer in

                NavigationLink(
                    destination: LocationList(selectedCustomer: customer)
                ) {
                    VStack(alignment: .leading){

                        Text("\(customer.name ?? "?")").font(.headline)

                        HStack{

                                    Spacer()
                                    Text("Locations: \(customer.locationList?.count ?? 0)")
                                        .font(.footnote)

                                }

                    }.padding()
                }

            }.onDelete(perform: self.removeCustomer)

        }

    }

    private func removeCustomer(at offsets: IndexSet) {

        for index in offsets {
            let obj = customerList[index]
            self.moc.delete(obj)
        }

        try? self.moc.save()

    }

}


Finally, this is my LocationList view:


struct LocationList: View {

    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    @Environment(\.managedObjectContext) var moc

    var requestLocations : FetchRequest<Location>
    var locationList : FetchedResults<Location>{requestLocations.wrappedValue}

    var selectedCustomer: Customer

    init(selectedCustomer: Customer){

        self.selectedCustomer = selectedCustomer

        self.requestLocations = FetchRequest(
            entity: Location.entity(),
            sortDescriptors: [],
            predicate: NSPredicate(format: "fromCustomer.id == %@", selectedCustomer.id!)
        )

    }

    var btnNewLocation : some View { Button(action: {

        let object = Location(context: self.moc)
        object.id = UUID().uuidString
        object.address = UUID().uuidString
        object.fromCustomer = self.selectedCustomer

        try? self.moc.save()

    })  {
        Image(systemName: "plus.circle.fill")
        }
    }

    var body: some View {

        VStack{

            List{

                ForEach(locationList, id: \.id) { location in

                    VStack(alignment: .leading){
                        Text("\(location.address ?? "?")").font(.headline)
                        .onTapGesture {

                            print("Tapped and changed selected parent object")

                            self.selectedCustomer.name = "Changed"

                            try? self.moc.save()

                            self.presentationMode.wrappedValue.dismiss()

                        }

                    }.padding()

                }
                .onDelete(perform: removeLocation)

            }


        }
        .navigationBarTitle(Text("\(selectedCustomer.name ?? "?")"), displayMode: .inline)
        .navigationBarItems(trailing: btnNewLocation)
    }

    private func removeLocation(at offsets: IndexSet) {

        for index in offsets {

            let obj = locationList[index]

            self.moc.delete(obj)

        }

        try? self.moc.save()

    }

}


This is the first view. Imagine I touched the last item:

There's no locations linked to the selected customer:

So, I added on new item:

The number of locations is still ZERO, but should be 1:

解决方案

A huge surprise in iOS: core data controllers only work on basic fields. Strange but true.

Incredibly, CoreData does not update based on relationships.

Only basic fields (int, string, etc).

You can see many QA and articles about this bizarre issue, example:

NSFetchedResultsController with relationship not updating

It is "just how it is".

There have been many attempts to work around this bizarre situation. There is no real solution. NSFetchedResultsController "is what it is" - it only works on basic fields (string, int, etc).

Unfortunately that is the situation.

Note: if I misunderstand the question here, sorry. But I believe this is the issue.

这篇关于SwiftUI核心数据不会刷新“一对多”消息。关系正确,列表未刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆