2009-04-09 43 views
0

我不知道的SQLite在後臺如何運行querys在What are best practices that you use when writing Objective-C and Cocoa?如何在iPhone的後臺運行sqlite?

這提示是我的嘗試:

- (void) run:(NSString *)sql { 
NSArray *data = [NSArray arrayWithObjects: 
       sql, 
       [self returnItemClass], 
       nil]; 

NSInvocationOperation *operation = 
[[NSInvocationOperation alloc] initWithTarget:self 
            selector:@selector(loadRecords:) 
             object:data]; 
[self.queue addOperation:operation]; 
[operation release]; 
} 

- (void) loadRecords:(NSArray *)data { 
    NSLog(@"Runing sql"); 
    NSString * sql = [data objectAtIndex:0]; 
    Class cls = [data objectAtIndex:1]; 

    Db *db= [Db currentDb]; 

    NSArray *list = [db loadAndFill:sql theClass:cls]; 
    [UIAppDelegate performSelectorOnMainThread:@selector(recordsLoaded:) 
              withObject:list 
             waitUntilDone:YES]; 
} 

- (void) recordsLoaded:(NSArray *)data { 
NSLog(@"Loading sql"); 
for (DbObject *o in data) { 
    [self.objectCache setObject:o forKey:[NSNumber numberWithInt:o.Id]]; 
} 
} 

不過,我得到一個錯誤,當嘗試運行

[UIAppDelegate performSelectorOnMainThread:@selector(recordsLoaded:) 
             withObject:list 
            waitUntilDone:YES]; 

抱怨關於不能發送消息給recordsLoaded。

這是正確的答案?

如何在UITableView中填充數據?

回答

2

作爲Apple的願望和設計的結果,多線程iPhone應用程序的方式並不太多。

但是,通用消息傳遞哲學有助於編寫面向事件的程序。您的程序應旨在通過將代表設置爲事件分派器來響應用戶輸入和環境變量。

作爲數據庫,SQLite3並不是傳統意義上的服務器。它與特定文件格式進行交互的協議,其中的庫可以直接包含在源代碼中。換句話說,當你需要從數據庫獲取數據時,你應該能夠立即讀取它。你不應該也不能在後臺產生一個SQLite3進程。

關於您所陳述的語法,你爲什麼用performSelectorOnMainThread...,而不是僅僅調用

[UIAppDelegate recordsLoaded:list] 

0
[UIAppDelegate performSelectorOnMainThread:@selector(recordsLoaded:) 
           withObject:list 
          waitUntilDone:YES]; 

應該

[self performSelectorOnMainThread:@selector(recordsLoaded:) 
         withObject:list 
        waitUntilDone:YES]; 

除非你定義爲UIAppDelegate像

#define UIAppDelegate ([UIApplication sharedApplication].delegate) 
0

我已經試過這兩種解決方案,他們的工作完美。您可以使用臨界區或NSOperationQueue,我更喜歡第一個,這裏是他們兩人的代碼:

定義一些類「DatabaseController」這個代碼添加到它的實現:

static NSString * DatabaseLock = nil; 
+ (void)initialize { 
    [super initialize]; 
    DatabaseLock = [[NSString alloc] initWithString:@"Database-Lock"]; 
} 
+ (NSString *)databaseLock { 
    return DatabaseLock; 
} 

- (void)writeToDatabase1 { 
    @synchronized ([DatabaseController databaseLock]) { 
     // Code that writes to an sqlite3 database goes here... 
    } 
} 
- (void)writeToDatabase2 { 
    @synchronized ([DatabaseController databaseLock]) { 
     // Code that writes to an sqlite3 database goes here... 
    } 
} 

OR使用NSOperationQueue你可以使用:

static NSOperationQueue * DatabaseQueue = nil; 
+ (void)initialize { 
    [super initialize]; 

    DatabaseQueue = [[NSOperationQueue alloc] init]; 
    [DatabaseQueue setMaxConcurrentOperationCount:1]; 
} 
+ (NSOperationQueue *)databaseQueue { 
    return DatabaseQueue; 
} 

- (void)writeToDatabase { 
    NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(FUNCTION_THAT_WRITES_TO_DATABASE) object:nil]; 
    [operation setQueuePriority:NSOperationQueuePriorityHigh]; 
    [[DatabaseController databaseQueue] addOperations:[NSArray arrayWithObject:operation] waitUntilFinished:YES]; 
    [operation release]; 
} 

這兩種解決方案阻止當前線程,直到寫入數據庫完成後,你可以在大多數的情況下考慮。