我有一个问题,我的核心数据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
}
由于
答案 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函数中的数据)