Я пытаюсь составить список всех объектов TestItem, но получаю эту ошибку:
'NSInvalidArgumentException', reason: '-[TestItem copyWithZone:]: unrecognized selector sent to instance.
Модель данных
ТестЭлем
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)")
}
}
}
Если в списке есть элементы, приложение вылетает при входе в ListElementsView. Я могу ввести его, если список пуст.
Я пытался сделать print(type(of: list.testitems)), он возвращает NSSet
Затем я попытался добавить print(list.testitems!.count), приложение вылетает.
Есть идеи?
В вашем вычисляемом свойстве itemArray вам нужно явно создать массив из вашего набора, а затем отсортировать массив. Сортировка набора не имеет смысла. И массив - это то, что вы говорите, что собираетесь вернуть
Не могли бы вы уточнить @Paulw11? Как я могу это сделать? Кроме того, я не думаю, что это проблема. Я нашел этот учебник, и он работает там
Правильно ли установлен параметр «к одному/ко многим»? И можно объявить все свойства NSManaged необязательными, чтобы избавиться от вопросительных знаков. @Paulw11 Вы можете отсортировать Swift Set. Он возвращает отсортированный массив.
Не называйте переменную List в SwiftUI, это имя встроенного типа, которое сбивает с толку при чтении и, возможно, также может создать проблемы при компиляции.





Оказалось, что vadian в комментариях был прав, я вообще не устанавливал параметр to-one/to-many.
Не используйте! Вызывает такие ошибки