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 devons pas effectuer de mise à jour de l'interface utilisateur à partir des threads d'arrière-plan. J'appelle un selector
fil principal comme ça -
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
Mais mon application plante dans la première étape. c'est-à-dire démarrer un fil d'arrière-plan. N'est-ce pas un moyen de démarrer des threads d'arrière-plan dans iOS?
MISE À JOUR 1: Après [self performSelectorInBackground....
avoir obtenu ce stacktrace, aucune information quoi que ce soit -
MISE À JOUR 2: J'ai même essayé de démarrer un fil d'arrière-plan comme celui-ci -
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
mais j'obtiens toujours le même stacktrace.
Juste pour que je clarifie, lorsque j'effectue cette opération sur le fil principal, tout se passe bien ...
MISE À JOUR 3 C'est la méthode que j'essaie d'exécuter en 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;
}
la source
docids
est conservé.docids
sontretain
. Je l'ai mis en.h
tant que@property (nonatomic, retain) NSMutableArray *docids;
get
; ça devrait juste êtreresultSetFromDB:
Réponses:
Si vous utilisez
performSelectorInBackground:withObject:
pour générer un nouveau thread, le sélecteur effectué est responsable de la configuration du pool de libération automatique du nouveau thread, de la boucle d'exécution et d'autres détails de configuration - voir «Utilisation de NSObject pour générer un thread» dans le Guide de programmation des threads d'Apple .Vous feriez probablement mieux d'utiliser Grand Central Dispatch , cependant:
GCD est une technologie plus récente, plus efficace en termes de surcharge mémoire et de lignes de code.
Mis à jour avec une pointe de chapeau à Chris Nolet , qui a suggéré un changement qui simplifie le code ci-dessus et suit les derniers exemples de code GCD d'Apple.
la source
[NSThread detachNewThreadSelector:@selector....
également?performSelectorInBackground:withObject:
"est le même que si vous appeliez ladetachNewThreadSelector:toTarget:withObject:
méthode deNSThread
avec l'objet actuel, le sélecteur et l'objet paramètre en tant que paramètres."(unsigned long)NULL
et0
dans ce domaine?Eh bien, c'est assez facile en fait avec GCD. Un flux de travail typique serait quelque chose comme ceci:
Pour en savoir plus sur GCD, vous pouvez consulter la documentation d'Apple ici
la source
Activez NSZombieEnabled pour savoir quel objet est libéré puis accédé. Vérifiez ensuite si cela
getResultSetFromDB:
a quelque chose à voir avec cela. Vérifiez également s'il ydocids
a quelque chose à l'intérieur et s'il est retenu.De cette façon, vous pouvez être sûr qu'il n'y a rien de mal.
la source
[self getResultSetFromDB:docids];
. Also when I try to call this method from background thread I do not reach
SpotMain * miroir ... `, Il plante peu de temps après être entré dans le thread d'arrière-plan ...La bibliothèque sqlite par défaut fournie avec iOS n'est pas compilée à l'aide de la macro SQLITE_THREADSAFE activée. Cela pourrait être une raison pour laquelle votre code plante.
la source
Réponse de Swift 2.x:
la source