swift 从NSManagedObject中删除为零的值

yptwkmov  于 6个月前  发布在  Swift
关注(0)|答案(2)|浏览(54)

我有一个问题,我的核心数据NSManagedObject在应用程序的第一次运行时总是有nil值。克服这个问题,我想我会尝试检查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
    }

pzfprimi

pzfprimi1#

你可以简单地检查值,如果有一个值,然后将其存储到下面的变量。试试下面的代码。

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
    }
}

字符串

qoefvg9y

qoefvg9y2#

所以你的问题是托管对象的属性为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)

            } else {

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

            }

字符串
(Don之后不要忘记保存托管上下文)
不过要小心!如果您的模型中有关系,并且您删除了一个托管对象,则该关系仍将存在,这意味着当您访问关系对象时,将存在nil对象(此处删除的对象)
编辑:为了确保tableView与dataSource(scoreData)同步,在变量声明中添加一个didSet函数,如下所示:

var scoreData = [NSManagedObject]() {
    didSet {
        tableView.reloadData()
    }
}


这意味着每次更改scoreData时,都会重新加载tableView(使用此函数,您不再需要在saveNew函数中重新加载数据)

相关问题