J'utilise NSURLSession pour obtenir les valeurs permettant de renseigner une table. Je mets à jour TableView dans le gestionnaire d'achèvement, mais l'utilisation de [[NSThread currentThread] isMainThread]
m'a montré que le gestionnaire d'achèvement ne s'exécute pas dans le thread principal. Comme je ne devrais mettre à jour que l'interface utilisateur à partir du thread principal, je sais que ce n'est pas correct. Existe-t-il un moyen de déclencher une action sur le thread principal à partir du gestionnaire d'achèvement? Ou bien utiliser une NSURLSession n'est-il pas la bonne façon de s'y prendre?
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
}] resume];
Oui, envoyez juste votre truc de fil principal en utilisant GCD
:
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
});
}] resume];
La réponse de @ Graver est bonne. Voici une autre façon de le faire:
NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
[[session dataTaskWithURL:[NSURL URLWithString:@"http://myurl"]
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *jsonError = nil;
NSArray* jsonUsers = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
NSLog(@"error is %@", [jsonError localizedDescription]);
// Handle Error and return
return;
}
self.userArray = jsonUsers;
[self.userTableView reloadData];
if ([[NSThread currentThread] isMainThread]){
NSLog(@"In main thread--completion handler");
}
else{
NSLog(@"Not in main thread--completion handler");
}
}] resume];
De cette façon, vous créez une session qui appelle le bloc d'achèvement et toutes les méthodes de délégation sur le thread principal. Vous pouvez trouver cela plus esthétique, mais vous perdez l’avantage de faire le "travail dur" en arrière-plan.
Vous pouvez essayer ceci:
[self.userTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
Voici le meilleur moyen de mettre à jour l'interface utilisateur à partir de blocs et du gestionnaire d'achèvement, et également lorsque vous ne précisez pas quel thread exécute votre code.
static void runOnMainThread(void (^block)(void))
{
if (!block) return;
if ( [[NSThread currentThread] isMainThread] ) {
block();
} else {
dispatch_async(dispatch_get_main_queue(), block);
}
}
Ceci est une méthode statique qui aura un bloc, et fonctionnera sur le thread principal, elle agira comme un
runOnMainThread(^{
// do things here, it will run on main thread, like updating UI
});
Swift 3.1
DispatchQueue.main.async {
tableView.reloadData()
}
envoyer une notification à la fin qui sera observée par le contrôleur de vue de table qui fera ensuite un reloadData;
cela présente l'avantage que si vous déplacez ce code de téléchargement ultérieurement vers une classe distincte, par exemple. un objet de modèle, aucune modification n'est requise et le code peut également être réutilisé dans d'autres projets sans modification