【发布时间】:2015-08-25 02:58:05
【问题描述】:
看这段代码:
型号:
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,但这并没有发生。我知道不是 let currentDay = daysArray[row] 我应该将 CoreData 中的 fetchedResultsController 归因于 currentDay,然后尝试更新 tableView。
我的问题是:我这样想是对的吗?我该怎么做?
我是 Swift 的新手,我希望有一些关于如何操作的示例。
提前致谢!!
更新 -> 完整代码
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()
}
}
【问题讨论】:
-
表格视图未重新加载的原因可能有多种。您也可以发布与表格视图相关的代码吗? detailsArray 是否还包含一些对象?还是空的?
-
我用完整的代码更新了问题! detailsArray 应该有 TrainingDetails 的对象。
-
我想你已经弄清楚了问题所在。您的表实际上是从 fetchRequestController 加载其内容,而不是从 details 数组。这就是为什么您的表没有重新加载与给定日期有关的详细信息。
标签: swift uitableview core-data uipickerview nsfetchedresultscontroller