aneuryzm
aneuryzm

Reputation: 64854

executeFetchRequest:error: causes an uncaught exception 'NSRangeException'

I'm getting a Out of Bounds exception in iOS4, which I don't get when I run my app in iOS5.

I get the exception when I invoke executeFetchRequest:error:

This is the code:

// Fetch
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"DisplayName = %@", inDisplayName];

    //iOS5 only
    //NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:inEntityName];

    NSFetchRequest *req = [[NSFetchRequest alloc] init];
    [req setEntity:[NSEntityDescription entityForName:inEntityName inManagedObjectContext:inContext]];

    [req setFetchLimit:1];
    [req setPropertiesToFetch:[NSArray arrayWithObject:@"DisplayName"]];
    [req setIncludesPropertyValues:NO];
    [req setIncludesSubentities:NO];
    [req setPredicate:pred];

    NSError *err = nil;
    NSArray * results = [inContext executeFetchRequest:req error:&err]; // here

    if ([results count]) {
        id result = [results objectAtIndex:0];
        [cache setObject:result forKey:cacheKey];        
        return result;
    }

    FreeAndNil(req);

And this is the log:

2012-08-23 10:47:35.855 MyApp [2694:11603] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 4294967295 beyond bounds [0 .. 30]'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x01cb15a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x02035313 objc_exception_throw + 44
    2   CoreFoundation                      0x01ca70a5 -[__NSArrayM objectAtIndex:] + 261
    3   CoreFoundation                      0x01bd674e CFArrayGetValueAtIndex + 190
    4   CoreData                            0x0193c304 -[NSSQLCore _prepareDictionaryResultsFromResultSet:usingFetchPlan:] + 2084
    5   CoreData                            0x018867ac -[NSSQLCore _newRowsForFetchPlan:selectedBy:withArgument:] + 2188
    6   CoreData                            0x0187d151 -[NSSQLCore newRowsForFetchPlan:] + 369
    7   CoreData                            0x0187c515 -[NSSQLCore objectsForFetchRequest:inContext:] + 357
    8   CoreData                            0x0187c0ce -[NSSQLCore executeRequest:withContext:error:] + 206
    9   CoreData                            0x0192bcdc -[NSPersistentStoreCoordinator executeRequest:withContext:error:] + 1084
    10  CoreData                            0x01879267 -[NSManagedObjectContext executeFetchRequest:error:] + 359
    11  MyApp                               0x0002519a +[CMItem objectWithEntityName:displayNameHasValue:inContext:] + 666
    12  MyApp                               0x00024c50 +[CMItem objectWithEntityName:andProperty:hasValue:inContext:] + 208
    13  MyApp                               0x00051ba7 -[CMMyEntity awakeFromInsert] + 295
    14  CoreData                            0x018b0647 -[NSManagedObjectContext insertObject:] + 151
    15  CoreData                            0x0188c680 -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:] + 336
    16  CoreData                            0x018b0a33 +[NSEntityDescription insertNewObjectForEntityForName:inManagedObjectContext:] + 131
    17  MyApp                               0x000909a4 -[CMEditViewControllerBase loadNewCollectible] + 212
    18  MyApp                               0x00091756 -[CMEditViewControllerBase saveButtonPushed:] + 614
    19  UIKit                               0x007204fd -[UIApplication sendAction:to:from:forEvent:] + 119
    20  UIKit                               0x00932cc3 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 156
    21  UIKit                               0x007204fd -[UIApplication sendAction:to:from:forEvent:] + 119
    22  UIKit                               0x007b0799 -[UIControl sendAction:to:forEvent:] + 67
    23  UIKit                               0x007b2c2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
    24  UIKit                               0x007b17d8 -[UIControl touchesEnded:withEvent:] + 458
    25  UIKit                               0x00744ded -[UIWindow _sendTouchesForEvent:] + 567
    26  UIKit                               0x00725c37 -[UIApplication sendEvent:] + 447
    27  UIKit                               0x0072af2e _UIApplicationHandleEvent + 7576
    28  GraphicsServices                    0x0244a992 PurpleEventCallback + 1550
    29  CoreFoundation                      0x01c92944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    30  CoreFoundation                      0x01bf2cf7 __CFRunLoopDoSource1 + 215
    31  CoreFoundation                      0x01beff83 __CFRunLoopRun + 979
    32  CoreFoundation                      0x01bef840 CFRunLoopRunSpecific + 208
    33  CoreFoundation                      0x01bef761 CFRunLoopRunInMode + 97
    34  GraphicsServices                    0x024491c4 GSEventRunModal + 217
    35  GraphicsServices                    0x02449289 GSEventRun + 115
    36  UIKit                               0x0072ec93 UIApplicationMain + 1160

thanks

UPDATE:

- (void)awakeFromInsert
{
    [super awakeFromInsert];
    [self setReadIt:[NSNumber numberWithBool:YES]];
    [self setCLZID:@"0"];
    CMLookUpItemComic *myRating = [CMItem objectWithEntityName:@"MyRating" andProperty:@"DisplayName" hasValue:@"0" inContext:[self managedObjectContext]];
    [self setMyRating:myRating];

    [self setUserValues:[NSEntityDescription insertNewObjectForEntityForName:@"UserValues" inManagedObjectContext:[self managedObjectContext]]];
}

Superclass:

- (void)awakeFromInsert
{
    [super awakeFromInsert];
    [self autoSetUniqueID];
}

- (void)autoSetUniqueID
{
    if (highestUniqueID == NSNotFound) {
        NSManagedObjectContext *context = [self managedObjectContext];
        NSEntityDescription *entity = [self entity];

        NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"UniqueID"
                                                             ascending:NO];
        NSArray *sortDescriptors = [NSArray arrayWithObject:sort];
        [sort release];

        NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
        [fetch setEntity:entity];
        [fetch setFetchLimit:1];

        [fetch setSortDescriptors:sortDescriptors];
        NSArray *results = [context executeFetchRequest:fetch error:nil];
        [fetch release];

        if (results != nil && [results count]) {
            CMItem *itemWithHighestID = [results lastObject];
            highestUniqueID = [[itemWithHighestID UniqueID] integerValue];
        } else {
            highestUniqueID = 0;
        }
    }

    highestUniqueID++;

    [self setPrimitiveValue:[NSNumber numberWithInt:highestUniqueID] forKey:@"UniqueID"];   
}

Upvotes: 1

Views: 530

Answers (2)

aneuryzm
aneuryzm

Reputation: 64854

For anyone getting into this issue and losing all day like me:

NSPredicate *pred = [NSPredicate predicateWithFormat:@"DisplayName = \"%@\"", inDisplayName];

The crash was caused by the missing brackets \"%@\" in the predicate/

Upvotes: 3

Paul de Lange
Paul de Lange

Reputation: 10633

What you have done makes me very nervous. From the Apple Docs:

You are typically discouraged from performing fetches within an implementation of awakeFromInsert. Although it is allowed, execution of the fetch request can trigger the sending of internal Core Data notifications which may have unwanted side-effects. For example, in OS X, an instance of NSArrayController may end up inserting a new object into its content array twice.

My suggestion is to remove the -awakeFromInsert code completely, and make highestUniqueID a transient property that is calculated each time it is required. You can retrieve the maximum value for a property very efficiently using Core Data. Read the section titled Fetching Specific Values.

You are trying to recreate the objectID. There is no reason for this code.

Upvotes: 0

Related Questions