J'ai un petit sqlitedb dans mon appareil iOS. Lorsqu'un utilisateur appuie sur un bouton, je récupère les données de sqlite et je les montre à l'utilisateur.
Cette partie de récupération je veux le faire dans un thread d'arrière-plan (pour ne pas bloquer le thread principal de l'interface utilisateur). Je fais ça comme ça -
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
Après la récupération et un peu de traitement, je dois mettre à jour l'interface utilisateur. Mais puisque (comme bonne pratique), nous ne devrions pas effectuer de mise à jour d’UI à partir de threads d’arrière-plan. J'appelle un selector
sur mainthread comme si -
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
Mais mon application se bloque dans la première étape. c'est-à-dire démarrer un fil de fond. N'est-ce pas un moyen de démarrer des threads en arrière-plan dans iOS?
PDATE 1: Après [self performSelectorInBackground....
je reçois ce stacktrace, aucune information de ce fait -
PDATE 2: J'ai même essayé de démarrer un thread d'arrière-plan comme celui-ci - [NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
mais je reçois toujours le même stacktrace.
Juste pour que je clarifie, quand j'effectue cette opération sur le fil principal, tout se passe bien ...
PDATE C'est la méthode que j'essaie de lancer à partir de l'arrière-plan
- (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;
}
Si vous utilisez performSelectorInBackground:withObject:
pour créer un nouveau thread, le sélecteur effectué est responsable de la configuration du pool de libération automatique, de la boucle d'exécution et des autres détails de configuration du nouveau thread - voir "Utilisation de NSObject pour générer un thread" dans Apple Guide de programmation de threads .
Vous feriez probablement mieux d'utiliser Grand Central Dispatch , cependant:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self getResultSetFromDB:docids];
});
GCD est une technologie plus récente et est plus efficace en termes de surcharge de mémoire et de lignes de code.
Mise à jour avec une pointe de chapeau à Chris Nolet , qui a suggéré une modification qui simplifie le code ci-dessus et reste en phase avec les dernières versions d'Apple. Exemples de code GCD.
En fait, c’est assez facile avec GCD. Un flux de travail typique serait quelque chose comme ceci:
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;
});
});
Pour plus d'informations sur GCD, vous pouvez consulter la documentation d'Apple ici
Activez NSZombieEnabled pour savoir quel objet est publié puis utilisé. Puis vérifiez si le getResultSetFromDB:
a quelque chose à voir avec cela. Vérifiez également si docids
a quelque chose à l'intérieur et s'il est conservé.
De cette façon, vous pouvez être sûr qu'il n'y a rien de mal.
Réponse rapide 2.x:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.getResultSetFromDB(docids)
}
La bibliothèque sqlite par défaut fournie avec iOS n'est pas compilée à l'aide de la macro SQLITE_THREADSAFE active. Cela pourrait être une raison pour laquelle votre code se bloque.