Core Data尝试访问NSSet属性时出现未识别的选择子发送给实例。

huangapple go评论64阅读模式
英文:

Core Data unrecognized selector sent to instance when trying to access a NSSet property

问题

如果列表中有项目,当我进入ListElementsView时应用程序会崩溃。如果列表为空,我可以进入它。

我尝试执行 print(type(of: list.testitems)),它返回 NSSet

然后我尝试添加 print(list.testitems!.count),应用程序崩溃。

有什么想法吗?

英文:

I am trying to make a list of all TestItem objects but I get this error:
'NSInvalidArgumentException', reason: '-[TestItem copyWithZone:]: unrecognized selector sent to instance.

Data model

TestItem

TestItemList

TestItemList+CoreDataProperties

import Foundation
import CoreData


extension TestItemList {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<TestItemList> {
        return NSFetchRequest<TestItemList>(entityName: "TestItemList")
    }

    @NSManaged public var name: String?
    @NSManaged public var testitems: NSSet?
    
    public var itemArray: [TestItem] {
        let set = testitems as? Set<TestItem> ?? []
        return set.sorted{
            $0.name! < $1.name!
        }
    }

}

extension TestItemList : Identifiable {
}

ContentView

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \TestItemList.name, ascending: true)],
        animation: .default)
    private var itemLists: FetchedResults<TestItemList>

    @State var listExists: Bool = false
    
    var body: some View {
        NavigationView {
            VStack{
                List{
                    ForEach(itemLists, id: \.self){ List in
                        NavigationLink(destination: ListElementsView(list: List)){
                            Text("\(List.name!)")
                        }
                    }.onDelete(perform: deleteItemList)
                }
                if(listExists){
                    Text("List exists!").foregroundColor(.red)
                }
                Button("Add today's list", action: {
                    addItemList()
                }).disabled(listExists).buttonStyle(.borderedProminent)
                List{
                    ForEach(testitems){
                        item in Text("\(item.name!), \(item.list!.name!)")
                    }
                }
            }
        }
    }
    
    private func addItemList() {
        let dateFormatter : DateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let date = Date()
        let dateString = dateFormatter.string(from: date)
        
        
        if(!itemLists.contains(where: {$0.name == dateString})){
            let newList = TestItemList(context: viewContext)
            newList.name = dateString
            
            do{
                try viewContext.save()
            } catch {
                let error = error as NSError
                fatalError("Error \(error), \(error.userInfo)")
            }
        }else{
            listExists = true
        }
    }

    private func deleteItemList(offsets: IndexSet) {
        withAnimation {
            offsets.map { itemLists[$0] }.forEach(viewContext.delete)

            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

private let itemFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .medium
    return formatter
}()

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}

ListElementsView

import SwiftUI

struct ListElementsView: View {
    @Environment (\.managedObjectContext) private var viewContext
    
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \TestItem.name, ascending: true)], animation: .default)
    private var testitems: FetchedResults<TestItem>

    var list: TestItemList
    
    @State private var text: String = ""
    
    var inputNotOk: Bool{
        text.isEmpty
    }
    
    var body: some View {
        VStack{
            Text(list.name!).font(.largeTitle)
            List{
                ForEach(list.itemArray){
                    obj in Text("\(obj.name!)")
                }.onDelete(perform: deleteTestItem)
            }
            Button("Add item", action: {
                addNewTestItem()
            }).disabled(inputNotOk).buttonStyle(.borderedProminent)
            TextField("item name", text: $text)
        }
    }
    
    private func addNewTestItem(){
        let newItem = TestItem(context: viewContext)
        newItem.name = text
        newItem.list = list
        do{
            try viewContext.save()
        } catch {
            let error = error as NSError
            fatalError("Error \(error), \(error.userInfo)")
        }
    }
    
    private func deleteTestItem(offsets: IndexSet){
        withAnimation{
            offsets.map{testitems[$0]}.forEach(viewContext.delete)
        }
        do{
            try viewContext.save()
        } catch {
            let error = error as NSError
            fatalError("Error \(error), \(error.userInfo)")
        }
    }
}

If the list has items, the app crashes when i enter ListElementsView. I can enter it if the list is empty.

I tried doing print(type(of: list.testitems)), it returns NSSet

Then i tried adding print(list.testitems!.count), the app crashes.

Any ideas?

答案1

得分: 0

原来评论中的vadian是对的,我根本没有设置一对一/一对多参数。

英文:

Turned out vadian in the comments was right, i didn't set the to-one/to-many parameter at all.

huangapple
  • 本文由 发表于 2023年6月19日 05:53:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76502667.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定