无法使用核心数据

时间:2016-11-25 15:14:17

标签: swift xcode core-data

首先我来自法国,对我的英语感到抱歉。

其次,我是开发人员的新手,我开发了一个添加数据的代码,然后用Core Data显示它们。它work.ok

但在我想要更新但我有问题后,我不知道为什么我无法更新我的价值。有一个错误:"致命错误:在打开一个可选值时意外发现nil"

我从1周开始尝试了很多解决方案,但无法找到问题。谢谢,如果有人可以帮助我!甚至一点帮助:)

这是我的代码(swift 2.3):

表格视图中显示:

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

1 个答案:

答案 0 :(得分:0)

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

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

理解非常重要,选择是什么以及如何在没有崩溃的情况下安全地处理它们。