8

I'm having a real bad time with this core data error.

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:     'statement is still active'

My app and code all works fine except occasionally when calling requests very quickly. It happens when I'm trying to break the app. Going from one screen to the next, downloading data and executing fetch requests.

I know it has something to do with threading and core data.

I'm calling this piece of code from a background thread, with it's own managed object context.

+ (AN_User *)updateWithRecord:(NSDictionary *)record moc:(NSManagedObjectContext *)moc{

    NSNumber *userID = nil;
    NSString *username = nil;

    if([record objectForKey:@"user_id"]){
        userID = [NSNumber numberWithInt:[[record objectForKey:@"user_id"] intValue]];
    }else if([record objectForKey:@"id_member"]){
        userID = [NSNumber numberWithInt:[[record objectForKey:@"id_member"] intValue]];
    }

    if([record objectForKey:@"username"]){
        username = [NSString stringWithFormat:@"%@", [record objectForKey:@"username"]];
    }else if([record objectForKey:@"member_name"]){
        username = [NSString stringWithFormat:@"%@", [record objectForKey:@"member_name"]];
    }

    if(!userID||!username){
        return nil;
    }

    __block AN_User *user = nil;

    [moc performBlockAndWait:^{

        NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];

        NSEntityDescription *entity = [NSEntityDescription entityForName:@"AN_User" inManagedObjectContext:moc];
        [request setEntity:entity];

        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(user_id == %@) OR (username == %@)", userID, username];
        [request setPredicate:predicate];

        if([moc countForFetchRequest:request error:nil]==0){
            user = (AN_User *)[NSEntityDescription insertNewObjectForEntityForName:@"AN_User" inManagedObjectContext:moc];
        }else{
            NSArray *fetchResults = [moc executeFetchRequest:request error:nil];
            if(fetchResults.count>0){
                user = [fetchResults objectAtIndex:0];
            }
        }

        if(user){

            user.user_id = userID;
            user.username = username.lowercaseString;

            //Parse profile image url
            NSString *avatar = [record objectForKey:@"avatar"];
            NSString *fileName = [record objectForKey:@"filename"];
            if([avatar isKindOfClass:[NSString class]]&&avatar.length>0){
                user.profile_image_url = [NSString stringWithFormat:@"%@", avatar];
            }else if([fileName isKindOfClass:[NSString class]]&&fileName.length>0){
                user.profile_image_url = [NSString stringWithFormat:@"http://www.example.com/forum/avs/%@", fileName];
            }

            if([record objectForKey:@"gpbp_respect"]){
                user.respect = [NSNumber numberWithFloat:[[record objectForKey:@"gpbp_respect"] floatValue]];
            }

        }
    }];
    return user;
}

I understand it's probably hard to tell from just this, but can anyone tell me if I'm doing anything wrong, with these requests, that is immediately obvious.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • [Add an exception breakpoint](http://stackoverflow.com/questions/4961770/run-stop-on-objective-c-exception-in-xcode-4). Trigger the error again. Copy the stack trace from the Debug Navigator and paste it into your question. – rob mayoff Dec 19 '12 at 09:54
  • Thanks. I tried to do this but I couldn't replicate the error. I think I've fixed it anyway. –  Dec 20 '12 at 07:12

1 Answers1

6

If you scroll a table that calls core data on a b/g thread, it happens and Core Data expects to have the context all on one thread.

Another SO poster worked around this by creating a MOContext per thread, but I don't like the idea of CRUD on multiple threads so I just put a dispatch_async (dispatch_get_main_queue(), ) wrapping function around my code. So far no crashes, but it's rare so I am not absolutely certain on this.

Stephen J
  • 2,367
  • 2
  • 25
  • 31