0

I'm getting this strange "use of unresolved identifier" warning, even though I'm declaring the var on the line above.

What's happening here? Here's my code:

var fetchedResultsController: NSFetchedResultsController<Project> {

    if _fetchedResultsController != nil {
        return _fetchedResultsController
    }

    let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest()

    fetchRequest.fetchBatchSize = 20

    let sortDescriptor = NSSortDescriptor(key: "name", ascending: false)

    fetchRequest.sortDescriptors = [sortDescriptor]

    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    do {
        try _fetchedResultsController.performFetch()
    } catch {
         // 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!
}

and here's the code from an Apple template project, which has no warnings or errors:

 var fetchedResultsController: NSFetchedResultsController<Event> {

    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest: NSFetchRequest<Event> = Event.fetchRequest()

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 20

    // Edit the sort key as appropriate.
    let sortDescriptor = NSSortDescriptor(key: "timestamp", ascending: false)

    fetchRequest.sortDescriptors = [sortDescriptor]

    // 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: nil, cacheName: "Master")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    do {
        try _fetchedResultsController!.performFetch()
    } catch {
         // Replace this implementation with code to handle the error appropriately.
         // fatalError() 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. 
         let nserror = error as NSError
         fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
    }

    return _fetchedResultsController!
}    

I'm beginning to think it might have something to do with the CoreData Entity (Class) I created (Project). Although it is a simple Entity with one attribute (name) - the template project also has one Entity (Event) with one attribute (timeStamp).

My "Tools Version" of the CoreData is set to Automatic (XCode 9.0) and the "Code Generation" is set to Swift.

Another thing I'm noticing is that XCode sometimes doesn't recognise my Entity (Project) and I have to restart to resolve that problem.

Is XCode 9 proving to be buggy with CoreData?

BillySangster
  • 408
  • 1
  • 3
  • 16
  • Dont post the image please post the code. Finally even if that compiles you will enter in infinite loop by accessing property in its getter. Are you by any chance trying to implement lazy var ?? – Sandeep Bhandari Dec 14 '17 at 09:02
  • I was going to post the code but the warnings didn't show up so it wouldn't demonstrate my problem properly. – BillySangster Dec 14 '17 at 09:22
  • You can post the code and error you can type it below. We cant copy your code and paste it in our workspace to check whats wrong in your code if you post the image :) – Sandeep Bhandari Dec 14 '17 at 09:24
  • 1
    I'll edit the question. – BillySangster Dec 14 '17 at 09:34
  • Please give a try to lazy variable. And if your concern is how apples code is working why not yours please ping the link to project lemme have a look n revert – Sandeep Bhandari Dec 14 '17 at 11:04
  • 1
    From the image in your first version, it seems the “undeclared identifier” is `_fetchedResultsController` which is different from `fetchedResultsController` - the underscore is hidden by the highlighting but is very relevant to the problem. The code you are using, which is a slight modification of Apple’s template, is a hangover from their ObjectiveC implementation of the FRC methods. In ObjectiveC properties are typically backed by instance variables, whose name is by default the property name with a leading underscore. – pbasdf Dec 14 '17 at 13:12
  • 1
    You should find that Apple’s template also has a `var _fetchedResultsController` defined, which you can copy to your code to resolve the problem. – pbasdf Dec 14 '17 at 13:13
  • Thanks, @pbasdf, that's exactly what was happening. In my stupidity I didn't notice the declaration of _fetchedResultsController which was right under the piece of code I shared. I feel so daft now! – BillySangster Dec 14 '17 at 18:14

1 Answers1

1

Looks like you are trying to create a singleton instance of NSFetchedResultsController or trying to initialize NSFetchedResultsController only once.

Issues:

Accessing the property directly within its getter will lead to infinite loop and app will crash.

Solution:

Probably all you need is lazy variable

lazy var fetchedResultsController : NSFetchedResultsController<Project> = {
    let localFetchedResultsController : NSFetchedResultsController< Project > = //initialize your fetched results controller
    return localFetchedResultsController
}()

This will ensure the fetchedResultsController being initialized only once and return the same instance again n again. Unless you intentionally change the instance itself by calling

self.fetchedResultsController = //some_new_fetchedResultsController_instance

Hope ut helps

EDIT 1:

Why dont you give a try to

lazy var fetchedResultsController : NSFetchedResultsController<Project> = {
        let fetchRequest: NSFetchRequest<Project> = Project.fetchRequest()
        fetchRequest.fetchBatchSize = 20
        let sortDescriptor = NSSortDescriptor(key: "name", ascending: false)
        fetchRequest.sortDescriptors = [sortDescriptor]

        let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: nil, cacheName: "Master")
        aFetchedResultsController.delegate = self

        do {
            try aFetchedResultsController.performFetch()
        } catch {
            // 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 aFetchedResultsController!
    }()
Sandeep Bhandari
  • 19,999
  • 5
  • 45
  • 78