从NSManagedObject中删除Nil值

时间:2016-10-01 11:44:50

标签: swift xcode null nsmanagedobject core

我有一个问题,我的核心数据NSManagedObject在第一次运行应用程序时总是在其中有nil值。克服这个问题我想我会尝试检查零值并在发现它们时删除它们。我尝试的代码如下:

do {
            let results = try managedContext.fetch(fetchRequest)
            scoreData = results as! [NSManagedObject]
            print(scoreData)
            for result in results as! [NSManagedObject] {

                if result.value(forKey: "name") as? String == nil || result.value(forKey: "date") as? String == nil || result.value(forKey: "score") as? String ==  nil {

                    managedContext.delete(result.value(forKey: "name") as! NSManagedObject)
                    managedContext.delete(result.value(forKey: "date") as! NSManagedObject)
                    managedContext.delete(result.value(forKey: "score") as! NSManagedObject)


                } else {

                name = result.value(forKey: "name") as! String
                date = result.value(forKey: "date") as! String
                score = result.value(forKey: "score") as! Int

                }

代码行'managedContext.delete()'让我很难,因为它没有正常工作。我使用了错误的方法还是我的代码不正确。欢迎任何帮助。

class LeaderboardTableVC: UITableViewController {

var finishedGame = 0 
var gameScore:Int! = 0
var name:String!
var date:String!
var score:Int!
var scoreData = [NSManagedObject]()

override func viewDidLoad() {
    super.viewDidLoad()

    if finishedGame == 1{
        saveNew()
    }



}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

func saveNew(){
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    let managedContext = appDelegate.persistentContainer.viewContext
    let entity = NSEntityDescription.entity(forEntityName: "Scores", in: managedContext)
    let object = NSManagedObject(entity: entity!, insertInto: managedContext)

        let enterNameAlert = UIAlertController(title: "Please Enter Your Name", message: "This will be used to place you in the leaderboards", preferredStyle: .alert)

        enterNameAlert.addTextField { (textField:UITextField) -> Void in
            textField.placeholder = "Name"
            textField.autocapitalizationType = UITextAutocapitalizationType.words
            textField.autocorrectionType = UITextAutocorrectionType.no
            textField.clearsOnBeginEditing = true
            textField.clearsOnInsertion = true
            textField.clearButtonMode = UITextFieldViewMode.always
            textField.keyboardType = UIKeyboardType.default

        }
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        let confirmAction = UIAlertAction(title: "Confirm", style: .default) { (action:UIAlertAction) in

            let currentTime = Date()
            let timeFormatter = DateFormatter()
            timeFormatter.locale = Locale.current
            timeFormatter.dateFormat = "HH:mm dd/MM/yy"
            let convertedTime = timeFormatter.string(from: currentTime)
            let enteredName = enterNameAlert.textFields?.first?.text

            object.setValue(convertedTime, forKey: "date")
            object.setValue(self.gameScore, forKey: "score")
            object.setValue(enteredName, forKey: "name")

            do {

                try managedContext.save()
                self.scoreData.append(object)
                self.tableView.reloadData()

            } catch let error as NSError  {
                print("Could not save \(error), \(error.userInfo)")
            }

        }

    enterNameAlert.addAction(cancelAction)
    enterNameAlert.addAction(confirmAction)
    self.present(enterNameAlert, animated: true, completion: nil)



}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! LeaderBoardCell
    let data = scoreData[(indexPath as NSIndexPath).row]

    if data.value(forKey: "date") as? String == nil || data.value(forKey: "score") as? Int == nil || data.value(forKey: "name") as? String == nil {

        print("Nil Value")

    } else {

    cell.dateLabel?.text = "Date: \((data.value(forKey: "date")) as! String)"
    cell.dateLabel.adjustsFontSizeToFitWidth = true
    cell.scoreLabel?.text = "Score: \((data.value(forKey: "score")) as! Int)"
    cell.scoreLabel.adjustsFontSizeToFitWidth = true
    cell.nameLabel?.text = "Name: \((data.value(forKey: "name")) as! String)"
    cell.nameLabel.adjustsFontSizeToFitWidth = true


    }
    return cell
    }

由于

2 个答案:

答案 0 :(得分:0)

如果有值,您只需检查值,然后将其存储到变量中,如下所示。尝试以下代码。

for result in results as! [NSManagedObject] {

    if let name = result.value(forKey: "name") {
        self.name = name as! String // if there will be a value in result for key 'name' then it will sore it. otherwise it won't let it be inside the if condition.
    }

    if let date = result.value(forKey: "date") {
        self.date = date as! String
    }

    if let score = result.value(forKey: "score") {
        self.score = score as! Int
    }
}

答案 1 :(得分:0)

所以你的问题是托管对象的属性是零,例如它们不存在。尝试删除值将不会执行任何操作,因为它们已不存在。相反,您可以删除托管对象,如下所示:

has_many :schools, :through => :school_survey_assignments

(不要忘记保存托管上下文)

虽然小心!如果您在模型中有关系并且删除了托管对象,则该关系仍然存在,这意味着当您访问关系对象时,将会有nil个对象(您在此处删除的对象)

编辑:为确保您的tableView与您的dataSource(scoreData)同步,请将didSet函数添加到您的变量声明中,如下所示:

do {
        let results = try managedContext.fetch(fetchRequest)
        scoreData = results as! [NSManagedObject]
        print(scoreData)
        for result in results as! [NSManagedObject] {

            if result.value(forKey: "name") as? String == nil || result.value(forKey: "date") as? String == nil || result.value(forKey: "score") as? String ==  nil {

                managedContext.delete(result)

            } else {

            name = result.value(forKey: "name") as! String
            date = result.value(forKey: "date") as! String
            score = result.value(forKey: "score") as! Int

            }

这意味着每次更改scoreData时都会重新加载tableView(您无需再使用此方法重新加载saveNew函数中的数据)