2011-04-25 62 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:模式: