прошивкой запустить фоновый поток
у меня есть небольшой sqlitedb в моем устройстве iOS. Когда пользователь нажимает кнопку, я извлекаю данные из sqlite и показываю их пользователю.
эта соблазнительная часть я хочу сделать это в фоновом потоке (чтобы не блокировать основной поток пользовательского интерфейса). Я делаю это так -
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
после извлечения и немного обработки, мне нужно обновить пользовательский интерфейс. Но поскольку (как хорошая практика) мы не должны выполнять обновление пользовательского интерфейса из фоновых потоков. Я называю selector на mainthread вот так -
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
но мое приложение падает на первом шаге. т. е. запуск фонового потока. Разве это не способ запуска фоновых потоков в iOS?
обновление 1: после [self performSelectorInBackground.... Я получаю этот stacktrace, нет информации, что так когда-либо -

обновление 2: я даже пробовал, начиная фоновый поток вот так -
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids]; но все равно я получаю тот же stacktrace.
так что Я уточняю, когда я выполняю эту операцию на основной поток все работает гладко...
обновление 3 это метод, который я пытаюсь запустить из фона
- (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids
{
SpotMain *mirror = [[SpotMain alloc] init];
NSMutableArray *filteredDocids = toProceessDocids;
if(![gMediaBucket isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1];
if(![gMediaType isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1];
if(![gPlatform isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1];
self.resultSet = [mirror FetchObjectFromDocid:filteredDocids];
[filteredDocids release];
[mirror release];
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
return;
}
5 ответов:
Если вы используете
performSelectorInBackground:withObject:чтобы создать новый поток, затем выполняемый селектор отвечает за настройку пула авторелиза нового потока, цикл запуска и другие сведения о конфигурации-см. "использование NSObject для создания потока" в Apple Руководство По Программированию Резьбы.вам, вероятно, будет лучше использовать Grand Central Dispatch, но:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self getResultSetFromDB:docids]; });GCD-это новая технология, и более эффективно с точки зрения памяти накладные расходы и строки кода.
Обновлено С кончиком шляпы к Крис Nolet, который предложил изменение, которое делает приведенный выше код проще и идет в ногу с последними примерами кода GCD от Apple.
Ну, это довольно легко на самом деле с GCD. Типичный рабочий процесс будет выглядеть примерно так:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul); dispatch_async(queue, ^{ // Perform async operation // Call your method/function here // Example: // NSString *result = [anObject calculateSomething]; dispatch_sync(dispatch_get_main_queue(), ^{ // Update UI // Example: // self.myLabel.text = result; }); });для получения дополнительной информации о GCD вы можете заглянуть в документация Apple здесь
включить NSZombieEnabled чтобы узнать, какой объект освобождается, а затем доступ. Затем проверьте, если
getResultSetFromDB:имеет к этому какое-то отношение. Также проверьте, еслиdocidsимеет что-нибудь внутри и если он сохраняется.таким образом, вы можете быть уверены, нет ничего плохого.
библиотека sqlite по умолчанию, которая поставляется с iOS, не компилируется с помощью макроса SQLITE_THREADSAFE on. Это может быть причиной сбоя кода.
Swift 2.х ответ:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { self.getResultSetFromDB(docids) }
Comments