• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
NSObjectInaccessibleException -- CoreData could not fullfill a fault
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

NSObjectInaccessibleException -- CoreData could not fullfill a fault


  • Subject: NSObjectInaccessibleException -- CoreData could not fullfill a fault
  • From: Steve Steinitz <email@hidden>
  • Date: Fri, 5 Oct 2007 22:40:33 +1000

Hello,

When an NSObjectInaccessibleException occurs, there is a chance that
the developer will be in a mild state of panic -- especially with a
live database.  So, for what its worth, I'll share the crude tool I
used to get out of hot water.

I made a new class called, say, DBOrphanRemover.

I added a method called deleteOrphanedObjects

deleteOrphanedObjects loops through all of the objects in the entities
(line items and payments) which I suspect to contain orphans (have
no sale or can't fulfill a sale fault) and deletes the ones with nil
sale.  Note that it puts the line item from each iteration into an
instance variable called currentObject.  I'll explain why below.

    NSFetchRequest *lineItemRequest = [[NSFetchRequest alloc] init];

    [lineItemRequest setEntity: [NSEntityDescription entityForName: @"LineItem"
                                            inManagedObjectContext: context ]];
    NSError *error = nil;

    NSArray *lineItems = [context executeFetchRequest: lineItemRequest
                                                error: &error];
    [lineItemRequest release];

    NSEnumerator * lineItemEnumerator = [lineItems objectEnumerator];
    Sale * sale;

    while (currentObject = [lineItemEnumerator nextObject])
    {
        sale = [(LineItem *) currentObject sale];
        if (nil == sale ||
            nil == [sale invoiceNumber])
        {
            [context deleteObject: currentObject];
            NSLog (@"deleted lineItem with null sale");
        }
    }

I more or less repeated that code for payments.

However, that isn't the full story.  While that code did delete some
of the orphaned objects, there were others that generated fault
fullfillment exceptions, stopped looping and so didn't examine further
objects.

So, to delete the excepting objects DBOrphanRemover had to catch an
exception and delete the object which was conveniently saved in
currentObject. (Sound foolhardy enough?)  Important: after each
exception, I  re-run the above loop again and again, by clicking a
'Delete Orphans' button, until finally, it finds no more orphaned
objects and all is hopefully well with the database.  I am too timid
to make it re-run automatically.

There are a few steps to handling the exception.
deleteOrphanedObjects saves the current exception handler delegate and
sets its DBOrphanRemover instance (self) as the delegate.

    id exceptionHandlerDelegate =
    [[NSExceptionHandler defaultExceptionHandler] delegate];
    [[NSExceptionHandler defaultExceptionHandler] setDelegate: self];

There are also a number of methods that need implementations for a
class handle exceptions.  I've shown my simple implementations at the
end of this post.

Here is the method that handles the exception.  My naivety of
exception handling nuances will be apparent to those of you having
more experience with them.

  - (BOOL)
    exceptionHandler:       (NSExceptionHandler *)  sender
    shouldHandleException:  (NSException *)         exception
                     mask:  (unsigned int)          aMask
    {
        if (nil != currentObject)
        {
            [context deleteObject: currentObject];
            NSLog (@"deleting Object that caused an exception");
        }
        return NO;
    }

At the end of the process, deleteOrphanedObject restores the original
exception handler delegate:

    [[NSExceptionHandler defaultExceptionHandler]
      setDelegate: exceptionHandlerDelegate];

I confess that this technique is full of danger and is so roughly hewn
that it may never be able to be made sound -- but, it got me out of hot
water and didn't appear to cause any problems.

I welcome comments and improvements.

Steve




Three other methods that need implementatios for exception handling:

 // filter out some common, harmless exceptions
  - (BOOL)
    shouldDisplayException: (NSException *) exception
    {
        NSString* name = [exception name];
        NSString* reason = [exception reason];

        if (    [name isEqualToString: @"NSImageCacheException"]            ||
                [name isEqualToString: @"GIFReadingException"]              ||
                [name isEqualToString: @"NSRTFException"]                   ||
               ([name isEqualToString: @"NSInternalInconsistencyException"] &&
                [reason hasPrefix:     @"lockFocus"])
           )
        {
            return NO;
        }
        return YES;
    }

  - (BOOL)
    exceptionHandler:   (NSExceptionHandler *)  sender
    shouldLogException: (NSException *)         exception
                  mask: (unsigned int)          aMask
    {
     // controls whether the exception shows up in the console, usually return YES
        return YES;
    }

  - (id)
    infoValueForKey: (NSString*) key
    {
        id result;
        if ([[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:key])
        {
            result = [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:key];
        }
        else
        {
            result = [[[NSBundle mainBundle] infoDictionary] objectForKey:key];
        }
        return result;
    }


---

Steve Steinitz         ph +61 (0)2 9487 7215
Director

Data Tactics
Sydney, Australia

www.datatactics.com.au

Web Commerce Development
Project Estimation and Planning
Software Development
MacOS X Support
_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Prev by Date: Problem using multiple stores with CoreData
  • Next by Date: Re: multiple methods named 'xxx' found.
  • Previous by thread: Problem using multiple stores with CoreData
  • Next by thread: Is ZLib available in Cocoa?
  • Index(es):
    • Date
    • Thread