moveToRow () и rowCount () в FMDB? - PullRequest
       11

moveToRow () и rowCount () в FMDB?

1 голос
/ 24 октября 2011

Мое приложение содержит 3000 экзаменационных вопросов в файле .sqlite. И эти вопросы выбираются динамически и сортируются по требованию пользователя (например, «сортировка по количеству неправильных ответов», «только выбор вопросов без доступа»).

Всякий раз, когда пользователь делает выбор, приложение делает соответствующий оператор SQL и, используя sqlite3, все наборы результатов отправляются в NSMutableArray (класс Question). Но, как вы заметите, это трудоемкий процесс (около 2 ~ 3 секунд, и пользовательский интерфейс перестает отвечать при этом).

Итак, я хочу создать класс «курсора», который имеет методы rowCount () и moveToRow (int index).

С этим моя идея

Cursor c = [[Cursor alloc] init] query(
    "SELECT id,qtext,answer,a1,a2,... FROM TABLE WHERE id > 100"
)]; 
    // at this time, just a cursor is given, no need to iterate all the retrieved rows

for (i=0; i > c.rowCount(); i++) {
    c.moveToRow(i);
    ShowQuestionDetail(c);
}

Вот так.

Я знаю, что CoreData подходит для этой цели, но мне нужно поделиться файлом .sqlite с версией этого приложения для Android. CoreData требует, чтобы все имена таблиц и полей начинались с префикса Z_, но я не могу изменить схемы файла .sqlite. Также мне нужно использовать sqlcipher, а CoreData не работает с sqlcipher.

FMDB не поддерживает методы, которые дают счетчик найденных строк и перемещаются к определенной строке.

Существуют ли другие библиотеки-оболочки SQLite, поддерживающие эту функцию?

Кто-то предлагает создать массив 'catalog', который содержит только идентификатор найденных строк и извлекать строку каждый раз, когда вызывается метод moveToRow (). Я согласен, что это хорошая альтернатива, но я хочу найти другой путь.

1 Ответ

1 голос
/ 13 марта 2012

Другой подход, возможно, ограничить ваш запрос 1 строкой данных. Это сделать вызов на cellForRowAtIndex. Из моего опыта - лучше иметь отдельный метод для этого - Вы могли бы даже сделать еще один шаг вперед и добавить слой DataCache для кэширования в памяти согласно coredata, если вам действительно это нужно.

Как то так .... http://code.google.com/p/airband/source/browse/trunk/airband/Classes/DataCache.h?spec=svn103&r=103

Например. - (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { // инициируем вашу клетку

 NSDictionary *dict = [self questionDataForCellAtIndexPath:indexPath];
 // set the cell values
}



-(NSDictionary*)questionDataForCellAtIndexPath:(NSIndexPath *)indexPath{

        //ENTER_METHOD;
    NSDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:0];

    NSString  *qry = [NSString stringWithFormat: @"SELECT id,qtext,answer,a1,a2,... FROM TABLE WHERE id ORDER BY id DESC limit 1 offset %d", [indexPath row]];

// you could look up here for previously accessed rows from DataCache
    //  NSDictionary *cachedRow = [DATAENV.cache objectForKey:num];
///if (cachedRow == nil) {
    //  go get it
   //   else return it 

    DLog(@"qry%@",qry );
     EGODatabaseResult *result  = [appDelegate.userdb executeQuery:qry];

    if ([result count]==0) {
        return dict;
    }
    for(EGODatabaseRow *row in result) {
        [dict setValue:[row stringForColumn:@"name"]  forKey:@"name"];

    }
    return dict;
}

проверь мою форк для EgoDatabase. https://github.com/jdp-global/egodatabase

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

...