1

currently, I'm trying to fetch an entity of type song on one of my view controllers. this is the code that's relevant, that I have:

import CoreData

class TimerScreenVC: UIViewController, NSFetchedResultsControllerDelegate {

var songController: NSFetchedResultsController<Song>!


override function viewDidLoad() {
   super.viewdidLoad()
   attemptSongFetch()
}


func attemptSongFetch() {
    let fetchRequest: NSFetchRequest<Song> = Song.fetchRequest()
    let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    let sortByTitle = NSSortDescriptor(key: "title", ascending: true)
    fetchRequest.sortDescriptors = [sortByTitle]
    songController = controller
    do {
        try songController.performFetch()
    } catch {
        let error = error as NSError
        print("\(error)")
    }


}


    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    print("called will change")
}
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    print("called did change")
}
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
    switch (type) {
    case .insert:
        print("has been called")
    default:
        print("has been called")
    }

}
}

however, when I load this view controller, I'm faced with the error "terminating with uncaught exception of type NSException". I can make the error go away and the program works fine if I comment out attemptSongFetch() in viewDidLoad(), but I need to call that function.

Also I have the exact same function, attemptSongFetch(), with the exact same code on another ViewController & that one isn't crashing. Any ideas? Any help would be greatly appreciated.

update so here's the error, it's telling me that I need to set the sort description, which is strange because it's already defined?:

017-02-20 15:48:21.006 Alarm Clock[10433:158613] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An instance of NSFetchedResultsController requires a fetch request with sort descriptors' libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

Spencer Milanak
  • 123
  • 2
  • 10
  • Don't know if it is the proble, but your fetch controller don't have delegate – CZ54 Feb 20 '17 at 14:47
  • I am assuming 'context' is nil. – Chandan kumar Feb 20 '17 at 14:54
  • 1
    "terminating with uncaught exception of type NSException" it not a a specific error. Include the **full error log** correctly. –  Feb 20 '17 at 14:59
  • see the comments on the question [here](http://stackoverflow.com/questions/26442414/libcabi-dylib-terminating-with-uncaught-exception-of-type-nsexception-lldb) and also see its answers – mfaani Feb 20 '17 at 15:03
  • @Chandan context is defined in the app delegate, it's essentially a shortcut variable defined as the appdelegate.persistentcontainer.viewContext – Spencer Milanak Feb 20 '17 at 20:40
  • @CZ54 is the fetch controller delegate not defined in the timerScreenVC class declaration? – Spencer Milanak Feb 20 '17 at 20:45
  • @SpencerMilanak No. You should explicitly assign it. controller.delegate = self – CZ54 Feb 22 '17 at 09:47

1 Answers1

5

The error message is pretty clear:

An instance of NSFetchedResultsController requires a fetch request with sort descriptors

At the moment you are creating the NSFetchedResultsController there are no sort descriptors (yet). Just reorder the lines:

let fetchRequest: NSFetchRequest<Song> = Song.fetchRequest()
let sortByTitle = NSSortDescriptor(key: "title", ascending: true)
fetchRequest.sortDescriptors = [sortByTitle]
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
vadian
  • 274,689
  • 30
  • 353
  • 361