Search code examples
iosuitableviewswiftnsfetchedresultscontrollersections

Sectioning TableView and rows with Core Data Swift


I have two tables in sqlite:

The code was generated by XCode Generation:

class Event: NSManagedObject {

    @NSManaged var startDate: NSDate
    @NSManaged var details: EventDetail  //i think this property shoud be var details Array<EventDetail>  am i correct?
}

class EventDetail: NSManagedObject {

    @NSManaged var title: String
    @NSManaged var location: String
    @NSManaged var note: String
    @NSManaged var endDate: NSDate
    @NSManaged var event: NSManagedObject
}

I want to put the events in section and the eventDetails in rows.

I created the method to load events:

var eventList : Array<AnyObject> = []

func loadEvents(){
    let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let moc: NSManagedObjectContext = appDel.managedObjectContext!
    let eventMO = NSFetchRequest(entityName: "Event")
    eventMO.returnsObjectsAsFaults = false

    var err : NSErrorPointer = nil
    eventList = moc.executeFetchRequest(eventMO, error: err)!
    self.tblEvento.reloadData()
}

func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
    return eventList.count
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {       
    //return (eventList[section] as Event).details.count
   return //????? what can i put here
}

I don't know what can i put in the method numbertOfRowsInSection to define the number of rows the section have. Because i can't access the details.count or something liked this.

I think there is other way to do this. I saw something as use NSFetchedResultsController but without sucess.

I would aprecciate some help.


Solution

  • Just a hint: If you're using CoreData and UiTableView use NSFetchedResultsController to make things much, much easier. If you're searching for a starting point & sample code - just create a new master-detail-application project in Xcode and turn on "Use Core Data" in the dialog.

    Now, straight to your question: an example "implementation" of the NSFetchResultsController:

    var fetchedResultsController: NSFetchedResultsController {

      if _fetchedResultsController != nil {
           return _fetchedResultsController!
       }
       let fetchRequest = NSFetchRequest()
       // Edit the entity name as appropriate.
       let entity = NSEntityDescription.entityForName("Event", inManagedObjectContext: self.managedObjectContext!)
       fetchRequest.entity = entity
    
       // Set the batch size to a suitable number.
       fetchRequest.fetchBatchSize = 20
    
       // Edit the sort key as appropriate.
       let sectionSortDescriptor = NSSortDescriptor(key: "startDate", ascending: true)
       let secondSortDescriptor = NSSortDescriptor(key: "title", ascending: true)
    
       let sortDescriptors = [sectionSortDescriptor, secondSortDescriptor]
    
       fetchRequest.sortDescriptors = sortDescriptors
    
       // Edit the section name key path and cache name if appropriate.
       // nil for section name key path means "no sections".
       let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: "startDate", cacheName: nil)
       aFetchedResultsController.delegate = self
       _fetchedResultsController = aFetchedResultsController
    
       var error: NSError? = nil
       if !_fetchedResultsController!.performFetch(&error) {
           // Replace this implementation with code to handle the error appropriately.
           // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
           //println("Unresolved error \(error), \(error.userInfo)")
           abort()
       }
    
       return _fetchedResultsController!
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return self.fetchedResultsController.sections?.count ?? 0
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionInfo = self.fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
        return sectionInfo.numberOfObjects
    }