Я сталкиваюсь с очень раздражающей проблемой. Мое приложение для iPhone загружается, это - данные из сетевого сервера. Данные отправляются как plist и при парсинге это должно быть сохранено к использованию дб SQLite CoreData.
Проблема - то, что в некоторых случаях те наборы данных являются слишком большими (5000 + записи), и импорт берет слишком долго. Больше на этом, когда iPhone пытается приостановить экран, Сторожевой таймер уничтожает приложение, потому что это все еще обрабатывает импорт и не отвечает до 5 секунд, таким образом, импорт никогда не заканчивается.
Я использовал все рекомендуемые методы в соответствии со статьей "Efficiently Importing Data" http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Conceptual/CoreData/Articles/cdImporting.html и другие документы относительно этого, но это все еще ужасно медленно.
Решение, которое я ищу, состоит в том, чтобы позволить приложению приостановить, но впустить импорт, выполненный позади (лучше один) или предотвратить попытки приостановить приложение вообще. Или любая лучшая идея одобрена также.
Любые подсказки относительно того, как преодолеть эти проблемы, высоко ценятся!Спасибо
Во-первых, если вы можете упаковать данные с приложением, которое было бы идеальным.
Тем не менее, предполагая, что вы не можете сделать это, то я бы сделал, затем следую:
В идеале отправка данных с приложением будет гораздо меньше работы, но второе решение будет работать, и вы можете точно настроить расставание данных во время разработки.
Вместо того, чтобы выталкивать файлы Plist на телефон, вы можете отправить готовые к использованию файлов SQLite. Это имеет много преимуществ:
Если вы всегда заменяете весь контент, просто перезапишите постоянный магазин в устройстве. В противном случае вы можете поддерживать массив как Plist со всеми SQLites, которые вы загрузили, а затем используете это, чтобы добавить все магазины в PersiStentStoreCoordinator.
Нижняя строка: используйте несколько предложенных файлов SQLite и добавьте их в персистентно -ordinator.
Вы можете использовать симулятор iPhone, чтобы создать эти хранилища COREDATA-SQLITE или использовать автономное приложение Mac. Вам нужно будет написать обоим тем самим собой.
Есть ли, что вы можете упаковать данные заранее - сказать во время развития? И когда вы толкаете приложение в магазин, некоторые данные уже есть? Это сокращает количество данных, которые вы должны потянуть, тем самым помогая решить эту проблему?
Если данные - это чувствительность к времени, или не готова, или по любой причине вы не можете сделать это, не могли бы вы сжать Данные с использованием сжатия ZLIB перед отправкой его по сети?
или проблема, которую телефон умирает 5k + вставки?
Я решил аналогичную проблему, поместив обработку вставки в фоновую резьбу. Но сначала я создал предупреждение о прогрессе, чтобы пользователь не мог манипулировать хранилищем данных, пока он вставлял записи.
Это в основном ViewControllers ViewBoadLoad
- (void)viewDidLoad
{
[super viewDidLoad];
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
// Only insert those not imported, here I know it should be 2006 entries
if ([self tableView:nil numberOfRowsInSection:0] != 2006) {
// Put up an alert with a progress bar, need to implement
[self createProgressionAlertWithMessage:@"Initilizing database"];
// Spawn the insert thread making the app still "live" so it
// won't be killed by the OS
[NSThread detachNewThreadSelector:@selector(loadInitialDatabase:)
toTarget:self
withObject:[NSNumber numberWithInt:[self tableView:nil
numberOfRowsInSection:0]]];
}
}
Нить вставки была сделана подобная это
- (void)loadInitialDatabase:(NSNumber*)number
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int done = [number intValue]+1; // How many done so far
// I load from a textfile (csv) but imagine you should be able to
// understand the process and make it work for your data
NSString *file = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"filename"
ofType:@"txt"]
encoding:NSUTF8StringEncoding
error:nil];
NSArray *lines = [file componentsSeparatedByString:@"\n"];
float num = [lines count];
float i = 0;
int perc = 0;
for (NSString *line in lines) {
i += 1.0;
if ((int)(i/(num*0.01)) != perc) {
// This part updates the alert with a progress bar
// setProgressValue: needs to be implemented
[self performSelectorOnMainThread:@selector(setProgressValue:)
withObject:[NSNumber numberWithFloat:i/num]
waitUntilDone:YES];
perc = (int)(i/(num*0.01));
}
if (done < i) // keep track of how much done previously
[self insertFromLine:line]; // Add to data storage...
}
progressView = nil;
[progressAlert dismissWithClickedButtonIndex:0 animated:YES];
[pool release];
}
, это немного грубые так, он пытается инициировать хранилище данных, откуда оно осталось, если пользователь будет остановить его предыдущий раз ...
Я представляю, что вы не показываете все 5K записей клиенту? Я бы порекомендовал выполнять все необходимые вами агрегацию на сервере, а затем отправлять только необходимые данные на телефон. Даже если это включает в себя генерацию нескольких различных видов данных, он все еще будет закаряями быстрее, чем отправка (а затем обработка) всех этих строк на iPhone.
Вы также обрабатываете данные в отдельном (без событии / UI) потоке?
Есть ли шанс настроить серверную часть для предоставления веб-службы RESTful для обработки ваших данных? У меня была аналогичная проблема, и я смог предоставить свою информацию через веб-сервис RESTful. На iphone есть библиотеки, которые упрощают чтение из подобного веб-сервиса. Я решил запросить JSON у службы и использовал библиотеку SBJSON на iphone, чтобы быстро получить полученные результаты и преобразовать их в словари для удобства использования. Я использовал библиотеку ASIHTTP для создания веб-запросов и постановки в очередь последующих запросов, а также для их работы в фоновом режиме.
В REST хорошо то, что он позволяет вам собирать пакеты информации, так что вам не нужно произвольно выяснять, как разбить файлы, которые вы хотите ввести. Вы просто устанавливаете, сколько записей вы хотите вернуть, и при следующем запросе вы пропускаете это количество записей. Я не знаю, подходит ли это вам вообще, поэтому я не буду сейчас вдаваться в множество примеров кода, но, если это возможно, это может быть простой способ справиться с этим.
Давайте согласимся с тем, что Restful (ленивая загрузка) не подходит ... Я так понимаю, вы хотите повторить. Если проблема с загрузкой относится к типу «все меньше и меньше строк загружается все больше и больше времени», то в псевдокоде ...
[self sQLdropIndex(OffendingIndexName)]
[self breathInOverIP];
[self breathOutToSQLLite];
[self sQLAddIndex(OffendingIndexName)]
Это должно вам многое рассказать.