swift - 无法使用核心数据更新值

标签 swift xcode core-data

首先我来自法国,很抱歉我的英语。

其次,我是开发新手,我已经开发了一个用于添加数据的代码,并在使用核心数据显示它们之后。它有效。确定

但是在我想要更新但遇到问题后,我不知道为什么无法更新我的值。出现错误:“ fatal error :在解包可选值时意外发现 nil”

自 1 周以来我已经尝试了很多解决方案,但找不到问题。谢谢如果有人可以帮助我!即使有一点帮助:)

这是我的代码(swift 2.3):

在表格 View 中显示:

import UIKit
import CoreData

class ProduitTableViewController: UITableViewController {

@IBOutlet var table: UITableView!

var produits = [NSManagedObject]()

func refreshStories(refreshControl: UIRefreshControl) {

        produits.removeAll()

        fetchData()
        self.table.reloadData()
        refreshControl.endRefreshing()

}

override func viewDidLoad() {
    super.viewDidLoad()

    self.fetchData()
    self.table.addSubview(self.refreshControl!)

    self.refreshControl?.addTarget(self, action: #selector(ProduitTableViewController.refreshStories(_:)), forControlEvents: UIControlEvents.ValueChanged)

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}

func fetchData() {

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext

    //2
    let fetchRequest = NSFetchRequest(entityName: "Produits")
    let sort = NSSortDescriptor(key:"dateAjout", ascending:true)
    fetchRequest.sortDescriptors = [sort]

    //3
    do {
        let results = try managedContext.executeFetchRequest(fetchRequest)
        produits = results as! [NSManagedObject]

    } catch let error as NSError {
        print("Donnees non recu \(error), \(error.userInfo)")
    }

}

// MARK: - Table view data source

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return self.produits.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell")

    let produit = produits[indexPath.row]

    cell!.textLabel!.text = produit.valueForKey("nom") as? String

    /*
    let id = produit.valueForKey("id") as? String
    let date = produit.valueForKey("date") as? NSDate
    let localNotification = UILocalNotification()
    localNotification.userInfo = ["id" : id!]
    localNotification.soundName = UILocalNotificationDefaultSoundName
    localNotification.alertBody = "expiré"
    localNotification.fireDate = date
    UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
    UIApplication.sharedApplication().applicationIconBadgeNumber += 1
    */

    return cell!
}

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

    let supprimer = UITableViewRowAction(style: .Normal, title: "Suppr.") { action, index in

        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        let moc = appDelegate.managedObjectContext

        // 3
        moc.deleteObject(self.produits[indexPath.row])
        appDelegate.saveContext()

        // 4
        self.produits.removeAtIndex(indexPath.row)
        tableView.reloadData()

    }
    supprimer.backgroundColor = UIColor.redColor()

    let update = UITableViewRowAction(style: .Normal, title: "Modifier") { action, index in

    }
    update.backgroundColor = UIColor.blueColor()

    return [supprimer]
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // the cells you would like the actions to appear needs to be editable
    return true
}

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

    if segue.identifier == "showDetail" {

        if let destination = segue.destinationViewController as? DetailViewController {

            let row = table.indexPathForSelectedRow?.row
            let produit = produits[row!]

            let nom = produit.valueForKey("nom") as? String
            let id = produit.valueForKey("id") as? String
            let detail = produit.valueForKey("detail") as? String
            let date = produit.valueForKey("date") as? NSDate

            let time = date
            let formatter = NSDateFormatter()
            formatter.dateFormat = "dd-MM-YY HH:mm"
            let formatteddate = formatter.stringFromDate(time!)

            destination.dataNom = nom!
            destination.dataId = id!
            destination.dataDetail = detail!
            destination.dataDate = formatteddate

        }

    }

}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if table.cellForRowAtIndexPath(indexPath) != nil {

        self.performSegueWithIdentifier("showDetail", sender: self)

    }

}

}

显示单元格的详细信息:

import CoreData
import UIKit

class DetailViewController: UIViewController {

@IBOutlet var Label: UILabel!
@IBOutlet var Detail: UITextView!
@IBOutlet weak var Date: UILabel!
@IBOutlet weak var Id: UILabel!

var dataNom = ""
var dataDetail = ""
var dataDate = ""
var dataId = ""

override func viewDidLoad() {
    super.viewDidLoad()

     Label.text = dataNom
     Detail.text = dataDetail
     Date.text = dataDate
     Id.text = dataId

    // Do any additional setup after loading the view

}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

    if segue.identifier == "ModifierDetail" {

        if let destination = segue.destinationViewController as? ModifierViewController {

            destination.modifierNom = dataNom
            destination.modifierId = dataId 
            destination.modifierDetail = dataDetail
            destination.modifierDate = dataDate

        }

    }

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

最后一个更新/修改我的详细信息:

import UIKit
import CoreData

class ModifierViewController: UIViewController {

@IBOutlet weak var Nom: UITextField!
@IBOutlet weak var Detail: UITextView!
@IBOutlet weak var Date: UITextField!

var Produits: NSManagedObject!
var managedContext: NSManagedObjectContext!

var modifierNom = ""
var modifierDetail = ""
var modifierDate = ""
var modifierId = ""

override func viewDidLoad() {
    super.viewDidLoad()

    Nom.text = modifierNom
    Detail.text = modifierDetail
    Date.text = modifierDate

    // Do any additional setup after loading the view.

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func Annuler(sender: UIBarButtonItem) {

    navigationController?.popViewControllerAnimated(true)

}


@IBAction func Modifier(sender: UIButton) {


    let fetchRequest = NSFetchRequest(entityName:"Produits")
    fetchRequest.predicate = NSPredicate(format: "nom = %@", modifierNom)

    do {

        let list = try managedContext.executeFetchRequest(fetchRequest) as! [Produit]
        if list.count == 0 // Check notificationId available then not save
        {

            let newManagedObject = NSEntityDescription.insertNewObjectForEntityForName("Produits", inManagedObjectContext: managedContext)
            newManagedObject.setValue(modifierNom, forKey: "nom")

        }
        // success ...
    } catch let error as NSError {
        // failure
        print("Fetch failed: \(error.localizedDescription)")
    }

}
/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

我已经创建了另一个文件:

import Foundation
import CoreData


@objc(Produit)
class Produit: NSManagedObject {
@NSManaged var nom:String!
}

最佳答案

正如您在评论中提到的,此行导致崩溃:

let list = try managedContext.executeFetchRequest(fetchRequest) as! [Produit]

该行并不安全,因为您不知道转换为 [Prodiut] 是否始终会成功。

一般来说,当您不 1000% 知道它会发生时,您永远不应该强制转换 (as!) 或强制解包 (!) 某些内容成功。

为了安全地施放,您可以使用guard:

guard let list = try managedContext.executeFetchRequest(fetchRequest) as! [Produit] else {
    //do some error handling here and then return
    return
}

之后,您就可以安全地使用list了。

了解什么是 optional 以及如何安全地处理它们而不导致崩溃非常重要。

关于swift - 无法使用核心数据更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40807985/

相关文章:

swift - Swift 3 中的 Alamofire 与 iOS 8

ios - 无法将类型 '[Thing]' 的值分配给类型 '[Any]' 的值

ios - 如何在核心数据上实现 transient 属性?

xcode - 如何发布预加载 coreData 的应用程序?

iphone - NSFetchRequest 内存问题

ios - 如何在 Alamofire Swift 中发送带数组的字典

swift - 在 mac 上快速获取电池百分比

swift - CollectionView 内的 TableView 内的单元格在首次加载时高度不正确(Swift 4)

xcode - 我可以在 XCode 中配置特定的资源吗

xcode - 带有多个参数的 NSPredicate