私は自分のUITableViewにアイテムがあり、セクションを決定する属性値を更新するのに苦労しています。セクションビューの行数がテーブルビューで更新されない
私はdidChangeSectionとオプションNSFetchedResultsChangeType.Updateと関係があることを知っています。しかし、それは私が得ることができる限りです。
セクション内の行数を更新するために必要なコードがわかりません。
これは私が取得しています正確なエラーコードです:
2016-04-17 20:00:37.126 EZ List[13722:1469523] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3512.60.7/UITableView.m:1716 2016-04-17 20:00:37.126 EZ List[13722:1469523] CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)
そして、これが私のビューコントローラのコードです:
import UIKit
import CoreData
class ListItemsTableViewController: UITableViewController, NSFetchedResultsControllerDelegate {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var frc: NSFetchedResultsController = NSFetchedResultsController()
var list: Lists?
var catalog: Catalog?
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
self.title = list?.name
frc = getFCR()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("Failed to perform inital fetch")
}
// Uncomment the following line to preserve selection between presentations
//self.clearsSelectionOnViewWillAppear = true
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func viewWillAppear(animated: Bool) {
let imageView = UIImageView(image: UIImage(named: "TableBackground"))
imageView.contentMode = .ScaleAspectFill
self.tableView.backgroundView = imageView
self.tableView.tableFooterView = UIView(frame: CGRectZero)
}
override func viewDidAppear(animated: Bool) {
frc = getFCR()
frc.delegate = self
do {
try frc.performFetch()
} catch {
fatalError("Failed to perform inital fetch")
}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let sections = frc.sections {
return sections.count
}
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = frc.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if let sections = frc.sections {
let currentSection = sections[section]
return currentSection.name
}
return nil
}
override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.backgroundColor = UIColor(red: 84/255, green: 200/255, blue: 214/255, alpha: 0.5)
header.textLabel!.textColor = UIColor.whiteColor()
//header.alpha = 0.5 //make the header transparent
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("listContentCell", forIndexPath: indexPath) as! ListItemsTableViewCell
let item = frc.objectAtIndexPath(indexPath) as! Items
cell.separatorInset = UIEdgeInsets(top: 0, left: 78, bottom: 0, right: 0)
cell.itemName.text = item.name
cell.itemSection.text = item.section
cell.itemQty.text = "Qty: \(item.qty!)"
cell.itemSize.text = item.size
cell.itemPrice.text = floatToCurrency(Float(item.cost!))
cell.itemImage.image = UIImage(data: item.image!)
cell.itemID.text = String(item.id!)
return cell
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.backgroundColor = UIColor.clearColor()
}
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let delete = UITableViewRowAction(style: .Destructive, title: "Delete") { (action, indexPath) in
let request = self.fetchRequest()
var fetchResults = [AnyObject]()
do {
fetchResults = try self.moc.executeFetchRequest(request)
} catch {
fatalError("Fetching Data to Delete Failed")
}
self.moc.deleteObject(fetchResults[indexPath.row] as! NSManagedObject)
fetchResults.removeAtIndex(indexPath.row)
do {
try self.moc.save()
} catch {
fatalError("Failed to Save after Delete")
}
}
let edit = UITableViewRowAction(style: .Normal, title: "Edit") { (action, indexPath) in
// Code to come
}
let qty = UITableViewRowAction(style: .Normal, title: "Qty") { (action, indexPath) in
// Code to come
}
edit.backgroundColor = UIColor.init(red: 84/255, green: 200/255, blue: 214/255, alpha: 1)
return [delete, edit, qty]
}
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case NSFetchedResultsChangeType.Delete:
self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
case NSFetchedResultsChangeType.Insert:
self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Automatic)
case NSFetchedResultsChangeType.Update:
let cell = self.tableView.cellForRowAtIndexPath(indexPath!) as! ListItemsTableViewCell
let item = self.frc.objectAtIndexPath(indexPath!) as! Items
cell.itemName.text = item.name
cell.itemSection.text = item.section
cell.itemQty.text = "Qty: \(item.qty!)"
cell.itemSize.text = item.size
cell.itemPrice.text = floatToCurrency(Float(item.cost!))
cell.itemImage.image = UIImage(data: item.image!)
cell.itemID.text = String(item.id!)
default:
print("didChangeObject Default was accessed")
break
}
}
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
switch type {
case NSFetchedResultsChangeType.Delete:
self.tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)
case NSFetchedResultsChangeType.Insert:
self.tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)
case NSFetchedResultsChangeType.Update:
self.tableView.reloadData()
default:
print("didChangeSection Default was accessed")
break
}
}
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Items")
let sortDesc1 = NSSortDescriptor(key: "section", ascending: true)
let sortDesc2 = NSSortDescriptor(key: "isChecked", ascending: true)
let sortDesc3 = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDesc1, sortDesc2, sortDesc3]
return fetchRequest
}
func getFCR() -> NSFetchedResultsController {
frc = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: moc, sectionNameKeyPath: "section" , cacheName: nil)
return frc
}
func getCatalog(id: NSNumber) -> Catalog {
var cat: Catalog?
let fetchReq = NSFetchRequest(entityName: "Catalog")
let pred = NSPredicate(format: "%K == %@", "id", id)
fetchReq.predicate = pred
do {
let check = try moc.executeFetchRequest(fetchReq)
cat = (check.first as! Catalog)
} catch {
fatalError("Failed fetching Catalog Entry matching Item")
}
return cat!
}
func floatToCurrency(flt: Float) -> String {
let formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
return String(formatter.stringFromNumber(flt)!)
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// 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?) {
var id: NSNumber
if (segue.identifier == "listItemView") {
let cell = sender as! UITableViewCell
let indexPath = self.tableView.indexPathForCell(cell)
let itemCont: ViewItemViewController = segue.destinationViewController as! ViewItemViewController
let item: Items = self.frc.objectAtIndexPath(indexPath!) as! Items
itemCont.item = item
id = item.id!
itemCont.catalog = getCatalog(id)
} else if (segue.identifier == "listItemViewEdit") {
let cell = sender as! UITableViewCell
let indexPath = self.tableView.indexPathForCell(cell)
let itemCont: AddItemListViewController = segue.destinationViewController as! AddItemListViewController
let item: Items = self.frc.objectAtIndexPath(indexPath!) as! Items
itemCont.item = item
id = item.id!
itemCont.catalog = getCatalog(id)
itemCont.list = list
}
}
}
私はそれを得るために本当に近いんだように感じますそうですね、私はその余分なプッシュが必要です。
私のコードに問題はなく、代わりにXcodeに問題があると思いますか? –
多分、はい、それはスレッドが言ったことです、何回NSFetchedResultsChangeTypeの実行を更新するか、挿入するか、または削除するときにブレークポイントで何回チェックを試みてください。最初に行をリロードしてみてください。 –