线程1-[主题addTasksObject:]:无法识别的选择器已发送到实例0x60000293cb00'

问题描述

我有一个带有核心数据模型的SwiftUI应用,其组织方式如下:

  • 对象“主题”具有某些属性以及与多个任务一对一的关系
  • 对象“任务”具有一些属性和一对一的主题关系

这是Task类扩展

extension Task {

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

    @NSManaged public var taskID: UUID
    @NSManaged public var name: String
    @NSManaged public var descr: String
    @NSManaged public var type: String
    @NSManaged public var date: Date
    @NSManaged public var priority: Int
    @NSManaged public var isCompleted: Bool
    @NSManaged public var notificationID: UUID
    @NSManaged public var subject: Subject

}

这是Subject类的扩展名:

extension Subject {

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

    @NSManaged public var name: String
    @NSManaged public var icon: String
    @NSManaged public var color: UIColor
    @NSManaged public var subjectID: UUID    
    @NSManaged public var tasks: NSSet?
    
    public var taskArray: [Task] {
        let set = tasks as? Set<Task> ?? []
        
        return set.sorted {
            $0.name < $1.name
        }
    }

}

// MARK: Generated accessors for tasks
extension Subject {

    @objc(addTasksObject:)
    @NSManaged public func addToTasks(_ value: Task)

    @objc(removeTasksObject:)
    @NSManaged public func removeFromTasks(_ value: Task)

    @objc(addTasks:)
    @NSManaged public func addToTasks(_ values: NSSet)

    @objc(removeTasks:)
    @NSManaged public func removeFromTasks(_ values: NSSet)

}

这是我创建新Task对象的视图:

struct NewTask: View {
    
    // MARK: - Variables
    
    @Binding var showSheet: Bool                // To close the sheet view and go back to home
    @State private var closeAlert: Bool = false // Close alert trigger
    
    @State private var name: String = ""        // Task's name
    @State private var type: TaskType = TaskType.Homework    // Task's type
    @State private var subject = Subject()      // Task's subject
    @State private var description: String = "" // Task's description
    @State private var priority: Int = 1        // Task's priority
    @State private var date: Date = Date()      // Task's date
    
    
    @State private var notificationEnabled: Bool = UserDefaults.standard.bool(forKey: "notificationsEnabled")
    
    @Environment(\.managedobjectContext) var moc        // Managed Object Context for Core Data managing
    
    @FetchRequest(entity: Subject.entity(),sortDescriptors: []) var subjects: FetchedResults<Subject>
    
    init() {
        self.subject = subjects[0]
    }
    
    // MARK: - View body
    
    var body: some View {
        NavigationView {
            Form {
                
                // Name input
                TextField("app.inputTask.name",text: $name)
                
                // Description input
                TextField("app.inputTask.description",text: $description)
                
                // Priority input
                HStack {
                    Stepper("app.inputTask.priority",value: $priority,in: 1...3)
                    Text(String(priority)).padding(.leading,10)
                }
                
                // Type input
                Picker(selection: $type,label: Text("app.inputTask.type")) {
                    ForEach(TaskType.allCases,id: \.self) {
                        Text(LocalizedStringKey($0.rawValue))
                    }
                }
                
                // Subject selection
                Picker(selection: $subject,label: Text("app.inputTask.subject")) {
                    ForEach(self.subjects,id: \.subjectID) { subject in
                        Text(subject.name)
                    }
                }
                
                // Date picker for date
                DatePicker(LocalizedStringKey("app.inputTask.date"),selection: $date,in: Date()...,displayedComponents: [.date,.hourAndMinute])
                
                Button(action: {
                    print("Materie:")
                    //print(subjects)
                },label: {
                    Text("Testing")
                })
            }
            
            
            
            
            .alert(isPresented: $closeAlert) {
                Alert(title: Text("app.warning"),message: Text("app.warning.discardChanges"),primaryButton: .default(Text("app.buttons.confirm"),action: {
                    self.showSheet.toggle()
                }),secondaryButton: .default(Text("app.buttons.cancel")))
            }
            
            .navigationBarTitle("app.tasks.newTask")
            
            .navigationBarItems(leading: HStack {
                Button(action: {
                    if !self.name.isEmpty || !self.description.isEmpty {
                        self.closeAlert.toggle()
                    } else {
                        self.showSheet.toggle()
                    }
                    
                }) {
                    Text("app.buttons.close").foregroundColor(Color.red).bold()
                }
            },trailing: HStack {
                Button(action: {
                    
                    // Create and save the object
                    let task = Task(context: self.moc)
                                        
                    task.name = self.name
                    task.descr = self.description
                    task.priority = self.priority
                    task.type = self.type.rawValue
                    task.date = self.date                    
                    task.taskID = UUID()
                    task.notificationID = UUID()
                    
                    // Relationship
                    task.subject = self.subject
                    subject.addToTasks(task)
                    
                    // Schedule the notification for the task
                    if self.notificationEnabled == true {
                        scheduleNotification(title: name,body: description,date: date,notifUUID: task.notificationID)
                    }
                    
                    // Close the new task view
                    self.showSheet.toggle()
                }) {
                    Text("app.buttons.save").bold()
                }
                .disabled(self.name.isEmpty == true)
            })
                        
        }
    }
}

要做的就是创建任务对象,并通过它们之间的关系将其链接主题。 但是,当我保存新的Task对象时,出现错误“由于未捕获的异常'NSinvalidargumentexception'而终止应用程序”,原因:'-[Subject addTasksObject:]:无法识别的选择器发送到实例0x60000293cb00' 以NSException类型的未捕获异常终止。”

我正在使用Xcode 12 beta,但我不认为这是一个错误,我认为在创建任务对象后建立关系时做错了事

解决方法

原因是在@State private var subject初始化中-您不能这样做,因为Subject()无效-它应该与上下文一起使用,但是上下文尚不可用,并且在{中没有更新{1}},因为获取请求尚未在初始化中执行,所以状态保持无效。

这里是解决此问题的一种可行方法(未经测试-由于代码不可测试,因此您可能需要修复编译器警告/错误)

请注意init声明/设置/使用位置。

subject