Eu tenho um pequeno sqlitedb em meu dispositivo iOS. Quando um usuário pressiona um botão, eu busco os dados do sqlite e os mostro ao usuário.
Esta parte de busca eu quero fazer em um thread de segundo plano (para não bloquear o thread principal da IU). Eu faço isso assim -
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
Após a busca e um pouco de processamento, preciso atualizar a IU. Mas já que (como uma boa prática), não devemos realizar a atualização da IU a partir de threads em segundo plano. Eu chamo um selector
no mainthread assim -
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
Mas meu aplicativo trava na primeira etapa. ou seja, iniciando um tópico de fundo. Não é uma maneira de iniciar threads em segundo plano no iOS?
ATUALIZAÇÃO 1: depois de [self performSelectorInBackground....
obter este rastreamento de pilha, nenhuma informação nunca -
ATUALIZAÇÃO 2: Eu até tentei, iniciando um thread de segundo plano assim -
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
mas ainda obtenho o mesmo rastreamento de pilha.
Só para que eu esclareça, quando eu executo essa operação no thread principal tudo funciona bem ...
ATUALIZAÇÃO 3 Este é o método que estou tentando executar em segundo plano
- (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;
}
fonte
docids
seja retido.docids
sãoretain
. Eu coloquei.h
como@property (nonatomic, retain) NSMutableArray *docids;
get
; isso deveria serresultSetFromDB:
Respostas:
Se você usar
performSelectorInBackground:withObject:
para gerar um novo thread, o seletor executado é responsável por configurar o pool de autorelease do novo thread, executar loop e outros detalhes de configuração - consulte "Usando NSObject para gerar um thread" no Guia de programação de threading da Apple .Você provavelmente ficaria melhor usando o Grand Central Dispatch , no entanto:
GCD é uma tecnologia mais recente e mais eficiente em termos de sobrecarga de memória e linhas de código.
Atualizado com uma dica de chapéu para Chris Nolet , que sugeriu uma mudança que torna o código acima mais simples e acompanha os exemplos de código GCD mais recentes da Apple.
fonte
[NSThread detachNewThreadSelector:@selector....
também?performSelectorInBackground:withObject:
"é o mesmo que chamar odetachNewThreadSelector:toTarget:withObject:
método deNSThread
com o objeto, seletor e objeto de parâmetro atuais como parâmetros."(unsigned long)NULL
e0
neste assunto?Bem, isso é muito fácil na verdade com GCD. Um fluxo de trabalho típico seria algo assim:
Para saber mais sobre GCD, você pode dar uma olhada na documentação da Apple aqui
fonte
Habilite NSZombieEnabled para saber qual objeto está sendo liberado e então acessado. Em seguida, verifique se o
getResultSetFromDB:
tem algo a ver com isso. Verifique também sedocids
há algo dentro e se está sendo retido.Dessa forma, você pode ter certeza de que não há nada errado.
fonte
[self getResultSetFromDB:docids];
. Also when I try to call this method from background thread I do not reach
SpotMain * mirror ... `, Ele trava logo após entrar no thread de background ...A biblioteca sqlite padrão que vem com o iOS não é compilada usando a macro SQLITE_THREADSAFE. Este pode ser o motivo pelo qual seu código falha.
fonte
Resposta do Swift 2.x:
fonte