2016-04-18 5 views
0

私は自分の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 
    } 

} 

} 

私はそれを得るために本当に近いんだように感じますそうですね、私はその余分なプッシュが必要です。

答えて

0

を助けている場合、これを確認してください。 didChangeObjectとNSFetchedResultsChangeType.Moveの問題でした。

次のコードは私の問題を解決しました。他のすべては同じなので、私はこれらの2つの機能を入れます。

NSFetchedResultsChangeType.Moveを追加し、その中に古い場所と新しい場所を削除します。

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: 
     tableView.reloadSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Automatic)*/ 
    default: 
     print("didChangeSection Default was accessed") 
     break 
    } 

} 

削除されたNSFetchedResultsChangeType.Updateは、セクションの更新を処理するためです。

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!) 
    case NSFetchedResultsChangeType.Move: 
     self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) 
     self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: UITableViewRowAnimation.Automatic) 
    } 

} 

これが他の人に役立つことを望みます。

1

は、あなたが話しているアップデートの行をリロードしてみて、それがだから、それはdidChangeSectionとNSFetchedResultsChangeType.Updateの問題ではありませんでし判明 https://forums.developer.apple.com/thread/12184

+0

私のコードに問題はなく、代わりにXcodeに問題があると思いますか? –

+0

多分、はい、それはスレッドが言ったことです、何回NSFetchedResultsChangeTypeの実行を更新するか、挿入するか、または削除するときにブレークポイントで何回チェックを試みてください。最初に行をリロードしてみてください。 –

関連する問題