0

看看這個代碼:CoreData - PickerView更新的tableView

型號:

import Foundation 
import CoreData 

class TrainingDetails: NSManagedObject { 

    @NSManaged var exerciseName: String 
    @NSManaged var repsNumber: String 
    @NSManaged var setsNumber: String 
    @NSManaged var trainingDay: TrainingDay 

} 

import Foundation 
import CoreData 

class TrainingDay: NSManagedObject { 

    @NSManaged var day: String 
    @NSManaged var dayIndex: NSNumber 
    @NSManaged var trainingDetails: NSSet 

} 

這個功能這裏

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 

     let currentDay = daysArray[row] 

     let fetchRequest = NSFetchRequest(entityName: "TrainingDetails") 
     let predicate = NSPredicate(format: "trainingDay.day == %@", currentDay) 
     fetchRequest.predicate = predicate 
     let sort = NSSortDescriptor(key: "exerciseName", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     detailsArray = (moc!.executeFetchRequest(fetchRequest, error: nil) as? [TrainingDetails])! 
     exerciseTableView.reloadData() 
    } 

現在,你可以看到,我有一個pickerView,其中應該更新tableView每次我選擇了一個不同的選項,但沒有發生。我知道,而不是讓currentDay = daysArray [行]我應該從CoreData fetchedResultsController屬性currentDay,然後嘗試更新tableView。

我的問題是:我有權這麼想嗎?我該怎麼做?

我是新來的斯威夫特,我會喜歡一些如何做到這一點的例子。

在此先感謝!

UPDATE - >全碼

import UIKit 
import CoreData 

class ExerciseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIPickerViewDataSource, UIPickerViewDelegate, NSFetchedResultsControllerDelegate { 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     VDL() 

     //sets stepper configs 
     setsStepper.wraps = false 
     setsStepper.autorepeat = true 
     setsStepper.continuous = true 
     setsStepper.tintColor = UIColor.redColor() 
     setsStepper.minimumValue = 0 
     setsStepper.maximumValue = 500 
     setsStepper.value = 0 

     //reps stepper configs 
     repsStepper.wraps = false 
     repsStepper.autorepeat = true 
     repsStepper.continuous = true 
     repsStepper.tintColor = UIColor.orangeColor() 
     repsStepper.minimumValue = 0 
     repsStepper.maximumValue = 500 
     repsStepper.value = 0 

     exerciseTableView.reloadData() 
    } 

    var moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext 
    var fetchedResultsController: NSFetchedResultsController? 

    @IBOutlet var exerciseTableView: UITableView! 

    @IBOutlet var daysPickerView: UIPickerView! 

    @IBOutlet var exerciseName: UITextField! 
    @IBOutlet var setsStepper: UIStepper! 
    @IBOutlet var repsStepper: UIStepper! 

    @IBOutlet var setsNumber: UILabel! 
    @IBOutlet var repsNumber: UILabel! 

    var daysArray = [TrainingDay]() 
    var detailsArray = [TrainingDetails]() 

    func VDL() { 

     let fetchRequest = NSFetchRequest(entityName: "TrainingDay") 
     let sort = NSSortDescriptor(key: "dayIndex", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     daysArray = (moc!.executeFetchRequest(fetchRequest, error: nil) as? [TrainingDay])! 
     if daysArray.count == 0 { // nothing there 
      let dayEntity = NSEntityDescription.entityForName("TrainingDay", inManagedObjectContext: moc!) 
      let days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] 
      for (index, name) in enumerate(days) { 
       let newDay = TrainingDay(entity: dayEntity!, insertIntoManagedObjectContext: moc) 
       newDay.day = name 
       newDay.dayIndex = index 
       daysArray.append(newDay) 
       println("NAME: \(newDay.day) INDEX: \(newDay.dayIndex)") 
      } 
      var error: NSError? 
      moc!.save(&error) 
     } 
    } 


    func appendTrainingDetailsToArray() { 
     let row = daysPickerView.selectedRowInComponent(0) 
     let currentDay = daysArray[row] 

     let detailsEntity = NSEntityDescription.entityForName("TrainingDetails", inManagedObjectContext: moc!) 
     let trainingdetails = TrainingDetails(entity: detailsEntity!, insertIntoManagedObjectContext: moc) 
     trainingdetails.exerciseName = exerciseName.text 
     trainingdetails.repsNumber = repsNumber.text! 
     trainingdetails.setsNumber = setsNumber.text! 
     trainingdetails.trainingDay = currentDay 

     var error: NSError? 
     moc?.save(&error) 

     if let err = error { 
      var status = err.localizedFailureReason 
      println("\(status)") 
     } else { 
      println("CURRENT SETTING: \(trainingdetails.trainingDay)") 
     } 
    } 

    func fetchTrainingDetails() -> NSFetchRequest { 

     let fetchRequest = NSFetchRequest(entityName: "TrainingDetails") 
     fetchRequest.predicate = nil 
     let sortDescriptor = NSSortDescriptor(key: "trainingDay", ascending: true) 
     fetchRequest.sortDescriptors = [sortDescriptor] 
     fetchRequest.fetchBatchSize = 20 
     return fetchRequest 
    } 

    @IBAction func doneButton(sender: AnyObject) { 
     appendTrainingDetailsToArray() 
     fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchTrainingDetails(), managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil) 
     fetchedResultsController?.delegate = self 
     fetchedResultsController?.performFetch(nil) 
     exerciseTableView.reloadData() 
    } 

    @IBAction func setsStepperAction(sender: UIStepper) { 
     println("\(Int(sender.value))") 
     setsNumber.text = Int(sender.value).description 
    } 

    @IBAction func repsStepper(sender: UIStepper) { 
     println("\(Int(sender.value))") 
     repsNumber.text = Int(sender.value).description 
    } 

    func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
     return fetchedResultsController?.sections?.count ?? 0 
    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return fetchedResultsController?.sections?[section].numberOfObjects ?? 0 
    } 

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

     let cell = tableView.dequeueReusableCellWithIdentifier("exerciseCell", forIndexPath: indexPath) as! UITableViewCell 
     let details = fetchedResultsController!.objectAtIndexPath(indexPath) as! TrainingDetails 
     cell.textLabel!.text = "\(details.exerciseName)" 
     cell.detailTextLabel!.text = "Sets: #\(details.setsNumber) Reps: #\(details.repsNumber)" 

     return cell 
    } 

    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool { 
     if self.fetchedResultsController == nil { 
      return false 
     } else { 
      return true 
     } 
    } 

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) { 
     println("section and row \(indexPath.section) \(indexPath.row) ") 
     if self.fetchedResultsController == nil { 
      println("error when trying to delete object from managed object") 

     } else if (editingStyle == UITableViewCellEditingStyle.Delete) { 

      switch editingStyle { 
      case .Delete: 
       moc?.deleteObject(fetchedResultsController?.objectAtIndexPath(indexPath) as! TrainingDetails) 
       moc?.save(nil) 
      case .Insert: 
       break 
      case .None: 
       break 
      } 
     } 
    } 

    //PICKER VIEW DELEGATE AND DATASOURCE METHODS 
    func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int { 
     return 1 
    } 

    func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { 
     return daysArray.count 
    } 

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { 
      let trainingDay = daysArray[row] 
      return trainingDay.day 
    } 

    func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 

     let currentDay = daysArray[row] 

     let fetchRequest = NSFetchRequest(entityName: "TrainingDetails") 
     let predicate = NSPredicate(format: "trainingDay.day == %@", currentDay) 
     fetchRequest.predicate = predicate 
     let sort = NSSortDescriptor(key: "exerciseName", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     detailsArray = (moc!.executeFetchRequest(fetchRequest, error: nil) as? [TrainingDetails])! 
     exerciseTableView.reloadData() 
    } 

    // MARK: NSFetchedResultsControllerDelegate 
    func controllerWillChangeContent(controller: NSFetchedResultsController) { 
     self.exerciseTableView.beginUpdates() 
    } 
    func controller(controller: NSFetchedResultsController, 
     didChangeObject anObject: AnyObject, 
     atIndexPath indexPath: NSIndexPath?, 
     forChangeType type: NSFetchedResultsChangeType, 
     newIndexPath: NSIndexPath?) 
    { 
     switch type { 
     case NSFetchedResultsChangeType.Insert: 
      // Note that for Insert, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Delete: 
      // Note that for Delete, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     case NSFetchedResultsChangeType.Update: 
      // Note that for Update, we update the row at __indexPath__ 
      if let updateIndexPath = indexPath { 
       let cell = self.exerciseTableView.cellForRowAtIndexPath(updateIndexPath) 
       let details = self.fetchedResultsController!.objectAtIndexPath(updateIndexPath) as? TrainingDetails 

       cell!.textLabel!.text = "\(details!.exerciseName)" 
       cell!.detailTextLabel!.text = "Sets: #\(details!.setsNumber) Reps: #\(details!.repsNumber)" 
      } 
     case NSFetchedResultsChangeType.Move: 
      // Note that for Move, we delete the row at __indexPath__ 
      if let deleteIndexPath = indexPath { 
       self.exerciseTableView.deleteRowsAtIndexPaths([deleteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 

      // Note that for Move, we insert a row at the __newIndexPath__ 
      if let insertIndexPath = newIndexPath { 
       self.exerciseTableView.insertRowsAtIndexPaths([insertIndexPath], withRowAnimation: UITableViewRowAnimation.Fade) 
      } 
     } } 

    func controller(controller: NSFetchedResultsController, 
     didChangeSection sectionInfo: NSFetchedResultsSectionInfo, 
     atIndex sectionIndex: Int, 
     forChangeType type: NSFetchedResultsChangeType) 
    { 
     switch type { 
     case .Insert: 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.exerciseTableView.insertSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
     case .Delete: 
      let sectionIndexSet = NSIndexSet(index: sectionIndex) 
      self.exerciseTableView.deleteSections(sectionIndexSet, withRowAnimation: UITableViewRowAnimation.Fade) 
     default: 
      "" 
     } 
    } 
    func controllerDidChangeContent(controller: NSFetchedResultsController) { 
     exerciseTableView.endUpdates() 
    } 
} 
+1

可能有幾個原因導致表視圖無法重新加載。你可以發佈你的表格視圖相關的代碼嗎? detailsArray是否包含一些對象?或者它是空的? – Shripada

+0

我用完整的代碼更新了問題! detailsArray應該有TrainingDetails的對象。 –

+0

我認爲你已經知道了什麼是問題。你實際上從fetchRequestController加載它的內容,而不是details數組。這就是爲什麼你的表沒有重新加載有關某一天的細節。 – Shripada

回答

1

所以,您需要更改與fetchedResultsController相關聯的讀取請求,並在其上調用performFetch(),然後重新加載表視圖。在您的

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { 
    let currentDay = daysArray[row] 
     //Update the fetch request related to the fetchedResultsController.fetchRequest that table view controller uses for its data 
     let fetchRequest = fetchedResultsController.fetchRequest 
     let predicate = NSPredicate(format: "trainingDay.day == %@", currentDay) 
     fetchRequest.predicate = predicate 
     let sort = NSSortDescriptor(key: "exerciseName", ascending: true) 
     fetchRequest.sortDescriptors = [sort] 
     //Perform fetch afresh 
     fetchedResultsController.performFetch(nil); 

     //Now reload the table view 
     exerciseTableView.reloadData() 
} 

參見:Documentation

修改獲取請求 你不能簡單地改變讀取請求 修改的結果。如果要更改提取請求,您必須:

如果您使用緩存,請將其刪除(使用deleteCacheWithName :)。

通常情況下,如果您要更改提取 請求,則不應使用緩存。

更改提取請求。

調用performFetch :.

+0

嘿!感謝您的回答!用你提供的代碼,假設我爲「星期一」添加了所有我想要的內容,現在我選擇另一行爲「星期二」,表格視圖重新加載但是爲空,如果我再次選擇「星期一」,它仍然是空的,不重新加載我添加的以前的東西。 –

+0

我在想:如果我們在選取器視圖中得到選定的行,提取它的名稱並將其分配給** var:string **並使用它而不是** let currentDay = daysArray [row] **?我猜問題出在那裏,currentDay沒有收到CoreData的適當日期,因爲** daysArrow **只是一個在這個表格視圖中正確排序的工具,保存的東西實際上並不保存在這個數組中。如我錯了請糾正我! –

+0

如果從選取器視圖中獲取字符串是解決方案,你能教我如何去做嗎? –