2016-11-25 74 views
0

首先,我來自法國,非常抱歉我的英語。無法用Core Data更新值

其次,我是開發新手,我已經開發了一個添加數據的代碼,並且在用Core Data顯示它們之後。它的作品.ok

但後我想更新,但我有一個問題,我不知道爲什麼我不能更新我的價值。有一個錯誤:「致命錯誤:意外地發現零,而解包可選值」

我已經嘗試了許多解決方案,因爲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! 
} 
+0

我現在很久很抱歉 –

+0

你知道,哪行代碼崩潰? – FelixSFD

+0

的可能重複[這是什麼?「致命錯誤:意外發現零而展開的可選值」的意思(http://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-同時,去包裹-AN-可選-VALU) – FelixSFD

回答

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

理解,選擇什麼以及如何在沒有崩潰的情況下安全地處理它們是非常重要的。

+1

正常情況下,如果您將某個已知實體提取爲給定的子類,則該提取會返回100%該類的非可選數組或引發錯誤。我想這是'Produit'與'Produits'不匹配 – vadian

+0

@vadian謝謝。不知道。我的核心數據工作並不多。 – FelixSFD

+0

非常感謝您的回答,我現在就試試。 –