Как запустить sqlite в фоновом режиме на iPhone? - PullRequest
0 голосов
/ 09 апреля 2009

Интересно, как запустить sqlite-запросы в фоновом режиме, как предложено в Какие рекомендации вы используете при написании Objective-C и Cocoa?

Это моя попытка:

- (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?

Ответы [ 4 ]

2 голосов
/ 09 апреля 2009

Многопоточность приложений для iPhone не так уж велика из-за пожеланий и дизайна Apple.

Общая философия обмена сообщениями, однако, способствует написанию ориентированных на события программ. Ваша программа должна стремиться реагировать на пользовательский ввод и переменные среды, устанавливая делегатов для диспетчеров событий.

SQLite3 как база данных не является сервером в классическом смысле. Это протокол для взаимодействия с определенным форматом файлов, библиотеки которого могут быть напрямую включены в исходный код. Другими словами, когда вам нужно получить данные из базы данных, вы сможете сразу же прочитать их. Вы не должны и не можете порождать процесс SQLite3 для работы в фоновом режиме.

Что касается вашего заявленного синтаксиса, почему вы используете performSelectorOnMainThread... вместо простого вызова

[UIAppDelegate recordsLoaded:list]

0 голосов
/ 22 августа 2011

Я пробовал эти два решения, и они отлично работали. Вы можете использовать критические разделы или 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...
    }
}

ИЛИ чтобы использовать 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];
}

эти два решения блокируют текущий поток до завершения записи в базу данных, что вы можете рассмотреть в большинстве случаев.

0 голосов
/ 10 апреля 2009
[UIAppDelegate performSelectorOnMainThread:@selector(recordsLoaded:)
                                withObject:list
                             waitUntilDone:YES];

должно быть

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

, если вы не определили UIAppDelegate как нечто вроде

#define UIAppDelegate ([UIApplication sharedApplication].delegate)
0 голосов
/ 09 апреля 2009
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...