2009-04-09 76 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]; 
} 

这两种解决方案阻止当前线程,直到写入数据库完成后,你可以在大多数的情况下考虑。