You are inside a inDatabase
call, iterating through a SELECT
statement and you then attempt to do another inDatabase
call. If you're going to do that, you probably want to pass the FMDatabase
as a parameter to the method, and not call inDatabase
again:
- (void)updateTrapInDatabase:(FMDatabase *)db distance:(double)distance trapID:(int)trapID distanceToClosePoint:(double)distanceToClosePoint
{
NSString *sqlStatment = [NSString stringWithFormat:@"UPDATE %@ SET %@=?, %@=? WHERE %@=?", TRAP_TABLE, DISTANCE, DISTANCE_TO_CLOSE_POINT, ID];
BOOL update = [db executeUpdate:sqlStatment, @(distance), @(distanceTpClosePoint), @(trapID)];
NSLog(@"Update trapID: %i, success: %@", trapID, update?@"YES":[NSString stringWithFormat:@"NO: %@", [db lastErrorMessage]]);
}
and replacing your call to:
[trapsDB updateTrapDistance:distance andTrapID:_id andDistanceToClosePoint:distanceToClosePoint];
with:
[trapsDB updateTrapInDatabase:db distance:distance trapID:_id distanceToClosePoint:distanceToClosePoint];
(As an aside, it's generally prudent to use ?
placeholders in your SQL (avoids precision related problems with float
variables, avoids SQL injection problems and quoting problems with NSString
variables), so I also tweaked the SQL above. Also, if a SQL statement fails, I always log lastErrorMessage
, otherwise I'm just guessing why the SQL failed. Use or disregard these unrelated tweaks as you see fit.)
But the main point is that one should never call inDatabase
while already in an inDatabase
. What's curious, though, is that calling inDatabase
while already in an inDatabase
generally causes a deadlock, not a "database is locked" error. Frankly, the entire purpose of FMDatabaseQueue
is to mediate database requests from different threads so that a database will never be busy. The only time you would generally receive "database is locked" error is if you had more than one FMDatabaseQueue
or FMDatabase
object. Your app should only have one database object open at any given time.