Nsobjectinaccessibleexception - Deleting all objects from an Entity - Nsfetchedresultscontroller

Asked

Viewed 61 times

1

I have a function responsible for deleting all items of an entity:

func removeItens() {
    if let managedContext = managedObjectContext {
        let fetchRequest = NSFetchRequest()

        let entity = NSEntityDescription.entityForName("Entidade", inManagedObjectContext: managedContext)
        fetchRequest.entity = entity
        fetchRequest.includesPropertyValues = false

        var error: NSError?
        var resultados = managedContext.executeFetchRequest(fetchRequest, error: &error)

        for resultado in resultados as [NSManagedObject] {
            managedContext.deleteObject(resultado)
        }

        if !managedContext.save(&error) {
            println("could not save \(error), \(error?.userInfo)")
        }
    }
}

My app consists of a Tabbar with 3 screens:

On the first tab, I have a city listing, and when selecting the user is sent to a product listing screen, on which he can "mark" the products.

The second tab has a screen that shows the listing of these marked products.

However, I need to delete all objects of this entity whenever the user selects a different city or when it starts the application after it is finished.

For the first case, I call the function in "prepareForSegue" when the user selects a city, and works perfectly.

The problem arises when I try to run in the second case. If I try to call this function in the "application didFinishLaunchingWithOptions" of Appdelegate or in the "viewDidLoad" of the first tab, the database is corrupted, and I get the following message when I try to enter the second tab:

Terminating app due to uncaught Exception 'Nsobjectinaccessibleexception', Reason: 'Coredata could not Fulfill a fault for '0xd000000000140000 ''

However, if I remove the function of the "application didFinishLaunchingWithOptions" or "viewDidLoad" from the first tab, the application works perfectly.

==Updated==

Watching more closely, the error is occurring in the second tab (the product listing).

I have a variable in which I use to keep updated the items in the table (in case the user marks some product).

lazy var fetchedResultsController: NSFetchedResultsController = {
    let fetchRequest = NSFetchRequest()

    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let managedContext = appDelegate.managedObjectContext!

    let entity = NSEntityDescription.entityForName("Entidade", inManagedObjectContext: managedContext)
    fetchRequest.entity = entity

    let sortDescriptor1 = NSSortDescriptor(key: "nome", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor1]

    let fetchedResultsController = NSFetchedResultsController(
        fetchRequest: fetchRequest,
        managedObjectContext: managedContext,
        sectionNameKeyPath: "nome",
        cacheName: "Entidade")

    fetchedResultsController.delegate = self
    return fetchedResultsController
}()

And the error is occurring right on this line:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.leftBarButtonItem = editButtonItem()

    var error: NSError?
    if !fetchedResultsController.performFetch(&error) { // <----- Esta
        fatalCoreDataError(error)
    }
}

Would anyone have any suggestions?

1 answer

1

The problem was entirely on the second tab.

The answer to the problem was to remove the variable:

lazy var fetchedResultsController: NSFetchedResultsController = {
    .
    .
    .
}()

Now the "viewDidLoad" of the second tab was as follows (fetch has been removed):

override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.leftBarButtonItem = editButtonItem()
}

Added the following variable:

var entidades = [Entidade]()

And added the following methods:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    fetchLog()
}

And

func fetchLog() {
    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let managedContext = appDelegate.managedObjectContext!

    let request = NSFetchRequest(entityName: "Entidade")

    var error: NSError? = nil

    if let results = managedContext.executeFetchRequest(request, error: &error) as? [Entidade] {
        self.entidades = results
    } else {
        println("Could not fetch \(error), \(error!.userInfo)")
    }
}

With these changes, I can finally remove the items when the application starts by placing the following code on the city listing screen:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    appDelegate.removeItens()
}

Or choose to call the "removeItens()" method in Appdelegate when the application starts or ends.

If anyone needs it, I can post the entire screen source code.

Updated

I found out what actually happened, I have a method in Appdelegate in which is responsible for updating the "badgeValue" of the listing tab, whenever a user marks a product.

It was as follows (and was called each time there was any change in managedObjectContext):

func atualizaUI() {
    let tabBarController = window!.rootViewController as UITabBarController

    if let tabBarViewControllers = tabBarController.viewControllers {
        let navigationController = tabBarViewControllers[3] as UINavigationController
        let listaViewController = navigationController.viewControllers[0] as ListaViewController
        listaViewController.managedObjectContext = managedObjectContext // <--- Aqui está o problema

        let fetchRequest = NSFetchRequest(entityName: "Entidade")
        if let fetchResults = managedObjectContext!.executeFetchRequest(fetchRequest, error: nil) {
            navigationController.tabBarItem.badgeValue = String(fetchResults.count)
        }
    }
}

I can not set the managedObjectContext to a screen this way, I need to assign it once in the "application didFinishLaunchingWithOptions", so I managed to keep the previous code to be able to enjoy the Nsfetcheultscontroller

Browser other questions tagged

You are not signed in. Login or sign up in order to post.