Core data 如何防止核心数据Swift 3中的删除规则拒绝出现错误

Core data 如何防止核心数据Swift 3中的删除规则拒绝出现错误,core-data,swift3,Core Data,Swift3,如何防止删除规则中出现错误?我有一个警报,要求用户删除一条记录,但检查是否可以删除它首先发生在核心数据堆栈中的save方法中。我试着用以下方法抓住它: if (self?.categoryToEdit.toMyplace == nil){ let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nich

如何防止删除规则中出现错误?我有一个警报,要求用户删除一条记录,但检查是否可以删除它首先发生在核心数据堆栈中的save方法中。我试着用以下方法抓住它:

if (self?.categoryToEdit.toMyplace == nil){
        let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nSie ist ", preferredStyle: .actionSheet)
        let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
            self?.tableView.setEditing(false, animated: true)
            self?.attemptFetch()
            self?.tableView.reloadData()
            return
        })
        alertController.addAction(cancelButton)
        self?.present(alertController, animated: false, completion: nil)
    }else{
        self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
    }
因此,我从编译器中得到一个错误:致命错误:在展开可选值时意外发现nil

我怎样才能解决它

提前感谢

编辑

谢谢大家!! 这里是完整的代码。 它在tableView操作中启动,并转发到处理警报的单独功能。此函数中未注释的部分实际上不起作用。当它处理错误时,我首先得到一个警报。 如果记录没有从tableView中消失,并在工作数组的索引中留下香,这将不会是一个大问题。 这个问题一直存在,直到应用程序重新启动,才有可能获得未删除的记录。我尝试新的fetch请求并重新加载表日期,但它会一直保持到新的开始

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let edit = UITableViewRowAction(style: .normal, title: "Ändern") { [weak self] action, index in
        self?.editMode = true
        let cell = tableView.cellForRow(at: indexPath) as! CategoryTVCell
        self?.configureCell(cell: cell, indexPath: indexPath)
        context.performAndWait{
            if let obj = self?.controller.fetchedObjects , obj.count > 0 {
                self?.categoryToEdit = obj[indexPath.row]
                self?.categoryToEditName = self?.categoryToEdit.name!
            }
        }
        self?.showAlertWithText()
        self?.showAlertWithText()
        tableView.isEditing = false
    }

    let delete = UITableViewRowAction(style: .normal, title: "Löschen") { [weak self] action, index in
        self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
    }

    edit.backgroundColor = UIColor(colorLiteralRed: 179.0/255.0, green: 179.0/255.0, blue: 179.0/255.0, alpha: 1)
    delete.backgroundColor = myRedAlertColor
    return [delete, edit]
}
private func displayActionSheet(indexPath: NSIndexPath)
{   let categoryName = categoryArray[indexPath.row]
    let alertController = UIAlertController(title: "Kategorie löschen", message: "Soll die Kategorie " + categoryName + " gelöscht werden?\r\nDie Kategorie kann nur gelöscht werden, wenn kein myPlace damit verbunden ist!", preferredStyle: .actionSheet)

    let deleteCategory = UIAlertAction(title: "Löschen", style: .destructive, handler: { [weak self](action) -> Void in
        self?.tableView.isEditing = false
        //if (self?.categoryToEdit.toMyplace == nil)/*((self?.myPlace?.toCateogry == nil))*/{
            context.delete((self?.controller.fetchedObjects?[indexPath.row])!)
            self?.categoryArray.remove(at: indexPath.row)
            self?.attemptFetch()
            self?.tableView.reloadData()
        //}else{
            /*let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nSie ist ", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)*/
        //}
        do{
            try context.save()
        }catch{
            let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nAlle myPlaces verlieren sonst diese Zuordnung!", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)

        }
    })

    let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
        self?.tableView.setEditing(false, animated: true)
    })

    alertController.addAction(deleteCategory)
    alertController.addAction(cancelButton)
    alertController.view.tintColor = .orange //UIColor(red: 0, green: 0, blue: 51)
    //self.navigationController!.present(alertController, animated: true, completion: nil)
    present(alertController, animated: false, completion: nil)
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let edit = UITableViewRowAction(style: .normal, title: "Ändern") { [weak self] action, index in
        self?.editMode = true
        let cell = tableView.cellForRow(at: indexPath) as! CategoryTVCell
        self?.configureCell(cell: cell, indexPath: indexPath)
        context.performAndWait{
            if let obj = self?.controller.fetchedObjects , obj.count > 0 {
                self?.categoryToEdit = obj[indexPath.row]
                self?.categoryToEditName = self?.categoryToEdit.name!
            }
        }
        self?.showAlertWithText()
        self?.showAlertWithText()
        tableView.isEditing = false
    }

    let delete = UITableViewRowAction(style: .normal, title: "Löschen") { [weak self] action, index in
        self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
    }

    edit.backgroundColor = UIColor(colorLiteralRed: 179.0/255.0, green: 179.0/255.0, blue: 179.0/255.0, alpha: 1)
    delete.backgroundColor = myRedAlertColor
    return [delete, edit]
}
private func displayActionSheet(indexPath: NSIndexPath)
{   let categoryName = categoryArray[indexPath.row]
    let alertController = UIAlertController(title: "Kategorie löschen", message: "Soll die Kategorie " + categoryName + " gelöscht werden?\r\nDie Kategorie kann nur gelöscht werden, wenn kein myPlace damit verbunden ist!", preferredStyle: .actionSheet)

    let deleteCategory = UIAlertAction(title: "Löschen", style: .destructive, handler: { [weak self](action) -> Void in
        self?.tableView.isEditing = false
        //if (self?.categoryToEdit.toMyplace == nil)/*((self?.myPlace?.toCateogry == nil))*/{
            context.delete((self?.controller.fetchedObjects?[indexPath.row])!)
            self?.categoryArray.remove(at: indexPath.row)
            self?.attemptFetch()
            self?.tableView.reloadData()
        //}else{
            /*let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nSie ist ", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)*/
        //}
        do{
            try context.save()
        }catch{
            let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nAlle myPlaces verlieren sonst diese Zuordnung!", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)

        }
    })

    let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
        self?.tableView.setEditing(false, animated: true)
    })

    alertController.addAction(deleteCategory)
    alertController.addAction(cancelButton)
    alertController.view.tintColor = .orange //UIColor(red: 0, green: 0, blue: 51)
    //self.navigationController!.present(alertController, animated: true, completion: nil)
    present(alertController, animated: false, completion: nil)
}
谢谢大家!! 这里是完整的代码。 它在tableView操作中启动,并转发到处理警报的单独功能。此函数中未注释的部分实际上不起作用。当它处理错误时,我首先得到一个警报。 如果记录没有从tableView中消失,并在工作数组的索引中留下香,这将不会是一个大问题。 这个问题一直存在,直到应用程序重新启动,才有可能获得未删除的记录。我尝试新的fetch请求并重新加载表日期,但它会一直保持到新的开始

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let edit = UITableViewRowAction(style: .normal, title: "Ändern") { [weak self] action, index in
        self?.editMode = true
        let cell = tableView.cellForRow(at: indexPath) as! CategoryTVCell
        self?.configureCell(cell: cell, indexPath: indexPath)
        context.performAndWait{
            if let obj = self?.controller.fetchedObjects , obj.count > 0 {
                self?.categoryToEdit = obj[indexPath.row]
                self?.categoryToEditName = self?.categoryToEdit.name!
            }
        }
        self?.showAlertWithText()
        self?.showAlertWithText()
        tableView.isEditing = false
    }

    let delete = UITableViewRowAction(style: .normal, title: "Löschen") { [weak self] action, index in
        self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
    }

    edit.backgroundColor = UIColor(colorLiteralRed: 179.0/255.0, green: 179.0/255.0, blue: 179.0/255.0, alpha: 1)
    delete.backgroundColor = myRedAlertColor
    return [delete, edit]
}
private func displayActionSheet(indexPath: NSIndexPath)
{   let categoryName = categoryArray[indexPath.row]
    let alertController = UIAlertController(title: "Kategorie löschen", message: "Soll die Kategorie " + categoryName + " gelöscht werden?\r\nDie Kategorie kann nur gelöscht werden, wenn kein myPlace damit verbunden ist!", preferredStyle: .actionSheet)

    let deleteCategory = UIAlertAction(title: "Löschen", style: .destructive, handler: { [weak self](action) -> Void in
        self?.tableView.isEditing = false
        //if (self?.categoryToEdit.toMyplace == nil)/*((self?.myPlace?.toCateogry == nil))*/{
            context.delete((self?.controller.fetchedObjects?[indexPath.row])!)
            self?.categoryArray.remove(at: indexPath.row)
            self?.attemptFetch()
            self?.tableView.reloadData()
        //}else{
            /*let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nSie ist ", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)*/
        //}
        do{
            try context.save()
        }catch{
            let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nAlle myPlaces verlieren sonst diese Zuordnung!", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)

        }
    })

    let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
        self?.tableView.setEditing(false, animated: true)
    })

    alertController.addAction(deleteCategory)
    alertController.addAction(cancelButton)
    alertController.view.tintColor = .orange //UIColor(red: 0, green: 0, blue: 51)
    //self.navigationController!.present(alertController, animated: true, completion: nil)
    present(alertController, animated: false, completion: nil)
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let edit = UITableViewRowAction(style: .normal, title: "Ändern") { [weak self] action, index in
        self?.editMode = true
        let cell = tableView.cellForRow(at: indexPath) as! CategoryTVCell
        self?.configureCell(cell: cell, indexPath: indexPath)
        context.performAndWait{
            if let obj = self?.controller.fetchedObjects , obj.count > 0 {
                self?.categoryToEdit = obj[indexPath.row]
                self?.categoryToEditName = self?.categoryToEdit.name!
            }
        }
        self?.showAlertWithText()
        self?.showAlertWithText()
        tableView.isEditing = false
    }

    let delete = UITableViewRowAction(style: .normal, title: "Löschen") { [weak self] action, index in
        self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
    }

    edit.backgroundColor = UIColor(colorLiteralRed: 179.0/255.0, green: 179.0/255.0, blue: 179.0/255.0, alpha: 1)
    delete.backgroundColor = myRedAlertColor
    return [delete, edit]
}
private func displayActionSheet(indexPath: NSIndexPath)
{   let categoryName = categoryArray[indexPath.row]
    let alertController = UIAlertController(title: "Kategorie löschen", message: "Soll die Kategorie " + categoryName + " gelöscht werden?\r\nDie Kategorie kann nur gelöscht werden, wenn kein myPlace damit verbunden ist!", preferredStyle: .actionSheet)

    let deleteCategory = UIAlertAction(title: "Löschen", style: .destructive, handler: { [weak self](action) -> Void in
        self?.tableView.isEditing = false
        //if (self?.categoryToEdit.toMyplace == nil)/*((self?.myPlace?.toCateogry == nil))*/{
            context.delete((self?.controller.fetchedObjects?[indexPath.row])!)
            self?.categoryArray.remove(at: indexPath.row)
            self?.attemptFetch()
            self?.tableView.reloadData()
        //}else{
            /*let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nSie ist ", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)*/
        //}
        do{
            try context.save()
        }catch{
            let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName + " kann nicht gelöscht werden!\r\nAlle myPlaces verlieren sonst diese Zuordnung!", preferredStyle: .actionSheet)
            let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
                self?.tableView.setEditing(false, animated: true)
                self?.attemptFetch()
                self?.tableView.reloadData()
            })
            alertController.addAction(cancelButton)
            self?.present(alertController, animated: false, completion: nil)

        }
    })

    let cancelButton = UIAlertAction(title: "Abbrechen", style: .cancel, handler: { [weak self](action) -> Void in
        self?.tableView.setEditing(false, animated: true)
    })

    alertController.addAction(deleteCategory)
    alertController.addAction(cancelButton)
    alertController.view.tintColor = .orange //UIColor(red: 0, green: 0, blue: 51)
    //self.navigationController!.present(alertController, animated: true, completion: nil)
    present(alertController, animated: false, completion: nil)
}
以下是解决方案:

let delete = UITableViewRowAction(style: .normal, title: "Löschen") 
{ 
   [weak self] action, index in

    do{
          try self?.controller.fetchedObjects?[indexPath.row].validateForDelete()
          self?.displayActionSheet(indexPath: indexPath as NSIndexPath)
       }catch{
          let categoryName = self?.categoryArray[indexPath.row]
          let alertController = UIAlertController(title: "Kategorie löschen", message: "Die Kategorie " + categoryName! + " kann nicht gelöscht werden!\r\nSie wird bereits verwendet!", preferredStyle: .actionSheet)
          let cancelButton = UIAlertAction(title: "Abbrechen", 
                                           style: .cancel, handler: { 

                        [weak self](action) -> Void in
                        self?.tableView.setEditing(false, animated: true)
                        self?.attemptFetch()
                        self?.tableView.reloadData()
            })

          alertController.addAction(cancelButton)
          self?.present(alertController, animated: false, completion: nil)
      }
}

它只是一个函数。validateForDelete()

请您共享执行删除操作的代码。还有,你的核心数据栈是什么样子的?请删除这篇文章,因为这是有问题的更新,我已经将这个更新合并到了问题中。