Загрузка 10k + строк в iphone SQLite (FMDB) - PullRequest
2 голосов
/ 26 сентября 2011

Я создаю приложение для словаря и пытаюсь загрузить термины в словарь iphone для использования.Термины определены из этой таблицы ( SQLite ):

id -> INTEGER autoincrement PK 
termtext -> TEXT
langid -> INT
normalized -> TEXT 

Нормализация используется, потому что я пишу на греческом языке, и у меня нет icu на движке sqlite для поиска диакритических знаковтаким образом, я делаю терминологический диакритический знак / нечувствительный к регистру.Это также основное поле поиска, в отличие от termtext, который может быть полем «view».

Я определил класс (например, POJO) следующим образом:

term.h

#import <Foundation/Foundation.h>
@interface Terms : NSObject {
 NSUInteger termId; // id
 NSString* termText; // termtext
 NSUInteger langId; // langid
 NSString* normalized; // normalized
}
@property (nonatomic, copy, readwrite) NSString* termText;
@property (nonatomic, copy, readwrite) NSString* normalized;
@property (assign, readwrite) NSUInteger termId;
@property (assign, readwrite) NSUInteger langId;
@end

term.c

#import "Terms.h"

@implementation Term
@synthesize termId;
@synthesize termText;
@synthesize langId;
@synthesize normalized;
@end

Теперь в своем коде я использую FMDB в качестве оболочки для SQLite база данных.Я загружаю термины, используя следующий код:

[... fmdb defined database as object, opened ]
NSMutableArray *termResults = [[[NSMutableArray alloc] init] autorelease];
FMResultSet *s = [database executeSQL:@"SELECT id, termtext, langid, normalized FROM terms ORDER BY normalized ASC"];
while ([s next]) {
 Term* term = [[Terms alloc] init];
 term.termId = [s intForColumn:@"id"];
 [... other definitions]
 [termResults addObject:term];
 [term release];
}

Затем весь termResults загружается в UITableView (на viewdidload), но загрузка занимает до 5 секунд каждый раз, когда я запускаю свойприложение.Есть ли способ ускорить этот процесс?Я проиндексировал id, termText и нормализовал на SQLite .

*** ОБНОВЛЕНИЕ: добавлено cellForRowAtIndexPath ****

[.. standard cell definition...]
// Configure the cell
Term* termObj = [self.termResults objectAtIndex:indexPath.row];
cell.textLabel.text = termObj.termText;
return cell;

Ответы [ 3 ]

2 голосов
/ 26 сентября 2011

Поскольку вы, похоже, все равно загружаете всю БД в память (и считаете это обязательным), весь смысл использования SQLite почти ушел.

Таким образом, если данные статические (не изменяются), я бы однажды превратил БД в объекты, затем сериализовал объекты (реализовал протокол NSCoding) и сохранил этот массив (или еще лучше). , словарь), используя writeToFile:atomically:. Получив этот файл (сделайте это во время разработки), вы можете легко загрузить его во время выполнения с помощью arrayWithContentsOfFile:, что в данном случае должно быть быстрее.

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

Загрузка такого количества данных в ваше приложение займет время. Лучший подход - загрузить данные из базы данных в отдельном потоке в основной поток приложения. Когда каждый элемент загружен, отправьте сообщение обратно в главный поток, чтобы добавить элемент в массив, поддерживающий табличное представление. Таким образом, время загрузки вашего приложения будет коротким, и ваш пользовательский интерфейс будет реагировать, пока данные загружаются из БД. Вот основная идея:

NSMutableArray *termResults = [NSMutableArray array];

// Load each item from the db on a separate thread using a block
dispatch_queue_t globalQueue = dispatch_get_global_queue();

dispatch_async(globalQueue, ^() {

  // Init the database
  ...
  // Load the items from the db
  FMResultSet *s = [database executeSQL:@"SELECT id, termtext, langid, normalized FROM    terms ORDER BY normalized ASC"];

  while ([s next]) {

    Term* term = [Term new];
    term.termId = [s intForColumn:@"id"];

    // Add the loaded item to termResults on the main thread
    // and refresh the table view
    dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();

    dispatch_async(mainDispatchQueue, ^() {
      // Add the loaded item to termResults
      [termResults addObject:term];
      // Refresh the table view. This will only reload the visible items.
      [tableView reloadData];
    });

    [term release];
  }
});

Надеюсь, это поможет.

0 голосов
/ 26 сентября 2011

Не проблема прочитать 10K записей из sqlite в UITableView. Во-первых, я не видел причин для этого. Во-вторых, вы не могли избежать временного промежутка из-за большого количества памяти. Выделение памяти - системный вызов. И системные вызовы часто медленные. Во время загрузки IOS будет отправлять предупреждения памяти для запуска приложений, что приводит к увеличению промежутка. Что вы будете делать, если вам понадобится миллион записей? sqlite используется, чтобы вообще избежать таких структур данных памяти. Если вы видите проблемы с использованием юникода в sqlite на iphone (icu) - прочитайте здесь . Я использую эту технику в нескольких своих приложениях, и все они без проблем были одобрены в AppStore.

...