Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLite Database with FMDatabase Wrapper

I am using the FMDatabase SQLite wrapper in Objective C and I have the following issue:

I am running an XML parse and DB insert in a background thread for some content that the user does not have access to, however the user is able to interact with a UI and database from the section they are in.

The FMDatabase <FMDatabase: 0x17b7b0> is currently in use.

Randomly, I will get a "FMDatabase already in use" notification and the array will never be populated by the database. I was under the impression that the FMDatabase class would handle the query once it became free, but I have a:

while(contents.count < 1){
     sleep(1);
}

Hoping that once the database frees up, the array will be populated. I have also tried rerunning the array population script if the DB is busy but to no avail.

Sorry if this question is confusing, I am happy to clarify.

like image 218
John Sloan Avatar asked Apr 25 '11 04:04

John Sloan


1 Answers

I experienced the same issue.

I switched to FMDatabaseQueue for every database query/update I had to do. It works like a charm !

Using performSelectorOnMainThread is a good idea but when it comes to actual coding it can be pretty tricky to pass your arguments and get the results for further use.

EDIT : here is a little example

-(void) updateTaskStateAsync:(NSNumber *)taskID withNewStatus:(NSNumber *)state andCompletionBlock:(void(^)(BOOL status))completionBlock{

    NSString *errInfo = [NSString stringWithFormat:@"taskID %d - state %d", [taskID intValue], [state intValue]];

    [queue inDatabase:^(FMDatabase *db) {
        BOOL r = [db executeUpdate:@"UPDATE tasks SET state=?, date_job_last_updated=? WHERE identifier=?", state, [NSDate dateWithTimeIntervalSinceNow:0], taskID];
        DB_DISPLAY_ERROR(errInfo); // convenient macro to log errors

        if(completionBlock)
            completionBlock(r);
    }];
}

-(BOOL) updateTaskStateSync:(NSNumber *)taskID withNewStatus:(NSNumber *)state {

    NSString *errInfo = [NSString stringWithFormat:@"taskID %d - state %d", [taskID intValue], [state intValue]];
    __block BOOL r = NO;
    __block BOOL ended = NO;

    [queue inDatabase:^(FMDatabase *db) {
        r = [db executeUpdate:@"UPDATE tasks SET state=?, date_job_last_updated=? WHERE identifier=?", state, [NSDate dateWithTimeIntervalSinceNow:0], taskID];
        DB_DISPLAY_ERROR(errInfo); // convenient macro to log errors

        ended = YES;
    }];

    NSCondition *cond = [[NSCondition alloc] init];
    [cond lock];
    while(!ended)
        [cond wait];

    [cond unlock];

    return r;
}
like image 180
dvkch Avatar answered Sep 21 '22 17:09

dvkch