title: Using UICollectionView with CoreData and NSFetchedResultsController
body: <p>I recently started another project exploring Swift a little bit. I want to implement a Collection View using a NSFetchedResultsController to get the data out of my CoreData database. I wanted to use the example from <a href="https://github.com/AshFurrow/UICollectionView-NSFetchedResultsController" rel="nofollow">https://github.com/AshFurrow/UICollectionView-NSFetchedResultsController</a>
  and implement something similar in Swift. I don't need any of the move events so I implemented the following:</p>
  
  <p>First of all I created a class to save changes made:</p>
  
  <pre><code>class ChangeItem{
      var index:NSIndexPath
      var type:NSFetchedResultsChangeType
  
      init(index: NSIndexPath, type: NSFetchedResultsChangeType){
          self.index = index
          self.type = type
      }
  }
  </code></pre>
  
  <p>within my collection view controller I use two arrays to save the changes temporarily</p>
  
  <pre><code>var sectionChanges:[ChangeItem] = []
  var objectChanges:[ChangeItem] = []
  </code></pre>
  
  <p>then I wait for my FetchedResultsController to change something after changes on the CoreData database were made</p>
  
  <pre><code>func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?,forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
      var item:ChangeItem?
      if(type == NSFetchedResultsChangeType.Insert){
          item = ChangeItem(index: newIndexPath!, type: type)
      }else if(type == NSFetchedResultsChangeType.Delete){
          item = ChangeItem(index: indexPath!, type: type)
      }else if(type == NSFetchedResultsChangeType.Update){
          item = ChangeItem(index: indexPath!, type: type)
      }
      if(item != nil){
          self.objectChanges.append(item!)
      }
  }
  
  func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
      var item:ChangeItem?
  
  
      if(type == NSFetchedResultsChangeType.Insert || type == NSFetchedResultsChangeType.Delete || type == NSFetchedResultsChangeType.Update){
          item = ChangeItem(index: NSIndexPath(forRow: 0, inSection: sectionIndex), type: type)
      }
      if(item != nil){
          self.sectionChanges.append(item!)
      }
  }
  </code></pre>
  
  <p>After all changes are applied the FetchedResultsController will perform the didChangeContent method</p>
  
  <pre><code>func controllerDidChangeContent(controller: NSFetchedResultsController) {
      println("something happened")
  
      self.collectionView!.performBatchUpdates({ () -&gt; Void in
          while(self.sectionChanges.count &gt; 0 || self.objectChanges.count &gt; 0){
              self.insertSections()
              self.insertItems()
              self.updateItems()
              let delips = self.deleteSections()
              self.deleteItems(delips)
          }
  
          }, completion: { (done) -&gt; Void in
              if(done){
                  println("done")
                  self.collectionView.reloadData()
              }else{
                  println("not done")
                  self.collectionView.reloadData()
              }
              if(self.fetchedResultsController.sections != nil &amp;&amp; self.fetchedResultsController.sections?.count &gt; 0){
                  println("number of items in first section \(self.fetchedResultsController.sections![0].count)")
              }
      })
  
  
      self.deselectAll()
      self.collectionView.reloadData()
      if(self.fetchedResultsController.sections != nil &amp;&amp; self.fetchedResultsController.sections!.count &gt; 0){
          for  i in 1 ..&lt; self.fetchedResultsController.sections!.count{
              if(self.fetchedResultsController.sections!.count &gt; 0){
                  println(self.fetchedResultsController.sections![i].numberOfObjects )
              }
          }
      }
  
  }
  </code></pre>
  
  <p>which then again calls the following methods </p>
  
  <pre><code>private func deleteSections()-&gt;NSIndexSet{
      var deletes = self.sectionChanges.filter({ (item) -&gt; Bool in
          if(item.type == NSFetchedResultsChangeType.Delete){
  
              let index = (self.sectionChanges as NSArray).indexOfObject(item)
              self.sectionChanges.removeAtIndex(index)
              return true
          }
  
  
          return false
      }) as [ChangeItem]
      var indexSet:NSMutableIndexSet = NSMutableIndexSet()
      for del in deletes{
  
          indexSet.addIndex(del.index.section)
      }
      if(indexSet.count &gt; 0 &amp;&amp; self.collectionView.numberOfSections() &gt; 0){
          self.collectionView.deleteSections(indexSet)
      }
      return indexSet
  }
  
  private func insertSections(){
      var inserts = self.sectionChanges.filter({ (item) -&gt; Bool in
          if(item.type == NSFetchedResultsChangeType.Insert){
              let index = (self.sectionChanges as NSArray).indexOfObject(item)
              self.sectionChanges.removeAtIndex(index)
              return true
          }
          return false
      }) as [ChangeItem]
      var indexSet:NSMutableIndexSet = NSMutableIndexSet()
      for ins in inserts{
          indexSet.addIndex(ins.index.section)
      }
      if(indexSet.count &gt; 0){
          println("Adding \(indexSet.count) section")
          println(indexSet)
  
          self.collectionView.insertSections(indexSet)
          self.collectionView.reloadSections(indexSet)
      }
  }
  
  private func deleteItems(deletedSections:NSIndexSet?){
      var deletes = self.objectChanges.filter({ (item) -&gt; Bool in
          if(item.type == NSFetchedResultsChangeType.Delete){
              let index = (self.objectChanges as NSArray).indexOfObject(item)
              self.objectChanges.removeAtIndex(index)
              return true
          }
      return false
      }) as [ChangeItem]
      var indexPaths:[NSIndexPath] = []
  
      for del in deletes{
          if(del.index.section &lt; self.fetchedResultsController.sections?.count){
  
              if(deletedSections == nil || deletedSections!.containsIndex(del.index.section)){
                  indexPaths.append(del.index)
              }
          }
      }
      /*indexPaths = indexPaths.sorted({ (a, b) -&gt; Bool in
          if(a.section &gt;= b.section &amp;&amp; a.row &gt;= b.row){
              return true
          }
          return false
      })
      println(indexPaths)*/
      //self.collectionView.numberOfItemsInSection(0)
      if(indexPaths.count &gt; 0){
          println("deleting \(indexPaths.count) items")
          self.collectionView.deleteItemsAtIndexPaths(indexPaths)
      }
  
  
  }
  private func updateItems(){
  
      var updates = self.objectChanges.filter({ (item) -&gt; Bool in
          if(item.type == NSFetchedResultsChangeType.Update){
              let index = (self.objectChanges as NSArray).indexOfObject(item)
              self.objectChanges.removeAtIndex(index)
              return true
          }
          return false
      }) as [ChangeItem]
      var indexPaths:[NSIndexPath] = []
      for update in updates{
          indexPaths.append(update.index)
      }
      if(indexPaths.count &gt; 0 ){
          println("did update on \(indexPaths.count) items")
          self.collectionView.reloadItemsAtIndexPaths(indexPaths)
      }
  
  }
  private func insertItems(){
      var inserts = self.objectChanges.filter({ (item) -&gt; Bool in
          if(item.type == NSFetchedResultsChangeType.Insert){
              let index = (self.objectChanges as NSArray).indexOfObject(item)
              self.objectChanges.removeAtIndex(index)
              return true
          }
          return false
      }) as [ChangeItem]
      var indexPaths:[NSIndexPath] = []
      for ins in inserts{
          indexPaths.append(ins.index)
      }
      if(indexPaths.count &gt; 0 &amp;&amp; self.numberOfSectionsInCollectionView(self.collectionView) &gt; 0){
  
          println("Adding \(indexPaths.count) items to collection view with \(self.collectionView.numberOfItemsInSection(0))")
          self.collectionView.insertItemsAtIndexPaths(indexPaths)
          println("Did add items")
      }
  
  }
  </code></pre>
  
  <p>Deleting multiple items and sections at a time works just fine (by now), but inserting a section does not work. As you can see I implemented a output within the insertSections method. The number of new sections in my test scenario is 1 and I get the right NSIndexSet with 1 item:(0). But in the insertItems method I try to call numberOfObjects on section 0 and get the following Error</p>
  
  <pre><code>*** Assertion failure in -[UICollectionViewData numberOfItemsInSection:], /SourceCache/UIKit_Sim/UIKit3347.44/UICollectionViewData.m:5942015-06-19:00:53:01.966 Grocli[42533:1547866] CoreData: error: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  request for number of items in section 0 when there are only 0 sections in the collection view with userInfo (null)
  </code></pre>
  
  <p>Thanks in advance for reading that long article and helping me out!</p>