2016-03-12 2 views
-3

Je suis trois appels d'API en cours d'exécution en utilisant l'API Spotify , afin d'obtenir les données suivantes et de les stocker dans mon objet Artist:Comment attendre pour terminer les appels async

  1. L'artiste.
  2. Les albums de cet artiste.
  3. Les pistes de chaque album de l'artiste.

Une fois qu'ils ont terminé, je voudrais passer l'objet à un autre contrôleur de vue. Il ressemble à ceci: (Si pouvez publier tout le code NSURLSession là-dedans si nécessaire)

func getArtist(artistName) { 
getAlbums(artistIdString)} 

func getAlbums(artistIdString) { 
a = Album 
Artist.albumsArray.append(a) 
for album in Artist.albumsArray { 
getTracks(albumIdString) 
} 
} 

func getTracks (albumIdString) { 
t = Track 
for album in Artist.albumsArray { 
    if idString == albumIdString { 
    album.append(t) 
    } 
} 
} 

func passArtist { 
DataStore.sharedInstance().Artist = Artist 
} 
+1

Possible duplication de [Comment exécuter séquentiellement deux fonctions asynchrones] (http://stackoverflow.com/questions/35551771/how-to-execute-two-asynchronous-functions-sequentially) – CouchDeveloper

+0

Si vous voulez appeler l'asynchrone fonctions _sequentially_ - c'est-à-dire appelez # 1, attendez jusqu'à la fin puis récupérez le résultat, appelez # 2 (éventuellement avec le résultat # 1 comme paramètre), attendez la fin, prenez le résultat # 2, etc. - vous devez avoir gestionnaire d'achèvement ou d'autres moyens pour informer l'appelant que la fonction asynchrone est terminée. Il y a déjà beaucoup de telles questions et aussi de bonnes réponses sur SO. – CouchDeveloper

+0

Votre problème peut aussi contenir un sous-problème spécial: un tableau d'entrées _N_ (par exemple des URLs) reçoit un tableau d'objets _N_ L'obtention de chaque objet nécessite l'appel d'une fonction asynchrone.Il existe également des solutions pour ce problème. été répondu à plusieurs reprises sur SO – CouchDeveloper

Répondre

0

Dans la fonction/bloc de rappel (ou , gestionnaire d'achèvement dans le terme Apple) de NSURLSession (ou NSURLSessionDataTask), exécutez une fonction de vérification. sur contre l'objet Artist actuel et voir si tous les 3 éléments requis étaient là (et si oui, appelez passArtist).

Peu importe la façon dont l'ordre d'arrivée est, il finira par appeler le passArtist une fois qu'il aura récupéré 3 éléments si vous l'avez fait.

Voici un exemple simple pour démontrer l'idée Objective-C (OP comme demandé):

- (void)getArtistDataWithRequest:(NSURLRequest *)request 
{ 
    NSURLSession   *session = [NSURLSession sharedSession]; 
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request 
               completionHandler:^(NSData  *data, 
                    NSURLResponse *response, 
                    NSError  *error) 
            { 
             if (error) 
             { 
              // Something went wrong, fallback. 
              NSLog(@"An error occurred: %@", error.localizedDescription); 

              // You could use some error handler e.g.: 
              // [self connectionDidFailWithError:error]; 

              return; 
             } 
             else if (response) 
             { 
              // Seems working, moving forward. 
              [self connectionDidReceiveSpotifyServerResponse:response 
                        andData:data]; 
             } 

            }]; 
    [task resume]; 
} 

- (void)connectionDidReceiveSpotifyServerResponse:(NSURLResponse *)aResponse 
              andData:(NSData *)aResponseData 
{ 
    // Do what you want here with the data you get, either it's album, track, 
    // or whatever. 

    // Assuming your "Artist" property is named "myArtist", and the "Artist" 
    // class has a method to process the data you get from Spotify API: 
    [_myArtist handleArtistData:aResponseData]; 

    // Now check your Artist object's element with another method. e.g.: 
    if ([_myArtist isLoadingComplete]) 
    { 
     // Done loading the object, pass it to view controller. 
    } 

    // Not yet done, do nothing for now. 
} 

Ceci est juste une solution. Il y a plusieurs façons de réaliser ce que vous voulez une fois que vous avez l'idée.

+0

Je suis désolé, quelle serait la syntaxe pour cela?[Audience dataTaskWithURL: [NSURL URLWithString: urlString] completionHandler:^(NSData * données, NSURLResponse * réponse, NSError * erreur) { if (error = zéro!) { NSLog (@ "Une erreur est survenue:% @ ", error.localizedDescription); retour; } –

+0

Je suppose que j'ai omis de mentionner que c'était un projet que j'ai fait dans swift et maintenant je fais dans l'objectif c. mais j'ai rencontré le même problème les deux fois. @ Zhi-Wei Cai –

+0

@SeanCalkins Voir ma réponse mise à jour. –

-4

Tout d'abord, comment allez-vous les trois appels API, en même temps? Ou l'utilisateur sélectionne d'abord l'artiste, puis vous faites un appel pour obtenir les albums, puis vous affichez des albums, puis l'utilisateur sélectionne un album et vous faites la troisième demande?

De toute façon, je vous suggère d'écrire la classe AsyncTask dans la classe Activity, puis vous pouvez utiliser un compteur pour attendre la fin des trois appels, puis sur la méthode onPostExecute() vous pouvez construire un objet Parcelable et passer dans le faisceau (intent.putExtra (authorObject) pour recevoir dans la méthode onCreate de la deuxième activité.

afficher ensuite les informations de la demande (je suppose que vous stockez dans un DB pour la mise en cache)

+4

la question est étiqueté avec iOS et Swift, pas Android ou Java –