2011-04-25 63 views
7

我使用目标C FMDatabase SQLite的包装,我有以下问题SQLite数据库可以访问,但是用户能够与他们在一节的UI和数据库交互。与FMDatabase包装

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

随机,我会得到一个“FMDatabase已在使用”通知和阵列将永远不会被填充由数据库。我的印象是,一旦它成为免费的FMDatabase类会处理的查询下,但我有一个:

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

希望,一旦数据库释放了,该阵列将被填充。我也尝试重新运行数组填充脚本,如果数据库很忙但无济于事。

很抱歉,如果这个问题是混乱的,我很乐意澄清。

回答

7

我经历了同样的问题。

我切换到FMDatabaseQueue每一个数据库查询/更新我不得不这样做。它像一个魅力!

使用performSelectorOnMainThread是一个好主意,但实际编码时,传递参数并获得结果供进一步使用可能非常棘手。

编辑:这里是一个小例子

-(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; 
} 
+0

我想要做的和你一样,但对于FMDatabaseQueue查询,其结果必然是回归异步.....是不是很方便。你有什么建议吗? – flypig 2012-08-20 14:38:18

+0

实际上我没有这个问题。我编辑了我的答案以添加一段代码,如果它没有帮助,请附上。 – dvkch 2012-08-21 07:50:37

+0

块代码由fmdb Queue异步执行,并且在代码执行时r会在块中更新,但是只需返回程序的最后一行中的r ....我想你会得到空的查询结果有时取决于fmdb队列状态。这严重地混淆了我好几天..可能是我们应该通过完成块返回查询结果,如“(BOOL)updateTaskState:(NSNumber *)taskID withNewStatus:(NSNumber *)state completion:(void(^)(BOOL r))completion;”并在[queue inDatabase:^(FMDatabase *)中调用completion(r) db){..}]块。 – flypig 2012-08-21 20:35:22

4

你遇到了这个问题,因为你的应用程序是多线程的,而且你正在从不同的线程访问同一个FMDatabase。类似的问题,但对于Python,可以找到here

FMDatabase是围绕SQLite的API的包装。 sqlite默认不支持并发性,所以FMDatabase使用一个名为“inUse”的成员变量来跟踪。要解决问题,请尝试对NSObject的定义,以便于FMDatabase所有呼叫在同一线程上发生这些方法之一。

  • performSelectorOnMainThread:withObject:waitUntilDone:
  • performSelectorOnMainThread:withObject:waitUntilDone:模式:
  • performSelector:onThread:withObject:waitUntilDone:
  • performSelector:onThread:withObject:waitUntilDone:模式: