-1

I am running three API calls using the Spotify API, in order to get the following data and store them into my Artist object:

  1. The artist.
  2. That artist's albums.
  3. Tracks of each albums of the artist.

Once they are done, I would like to pass the object to a different view controller. It looks something like this: (If could post all the NSURLSession code in there if necessary)

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
}
Cai
  • 3,609
  • 2
  • 19
  • 39
Sean Calkins
  • 312
  • 2
  • 11
  • 1
    Possible duplicate of [How to execute two asynchronous functions sequentially](http://stackoverflow.com/questions/35551771/how-to-execute-two-asynchronous-functions-sequentially) – CouchDeveloper Mar 14 '16 at 14:01
  • If you want to call the asynchronous functions _sequentially_ -- that is, call #1, wait until finished then retrieve the result, call #2 (possibly with result #1 as parameter), wait until finished, take result #2, etc. -- you have to have a completion handler or other means to notify the caller that the async function finished. There are already many such questions and also good answers on SO. – CouchDeveloper Mar 14 '16 at 14:01
  • Your problem _may_ also contain some special "sub-problem: having an array of _N_ inputs (for example URLs) get an array of _N_ objects. Obtaining each object requires to call an asynchronous function. There are also solutions for this problem that have been answered many times on SO. – CouchDeveloper Mar 14 '16 at 14:09

3 Answers3

0

In the callback function/block (or completion handler in Apple's term) of NSURLSession (or NSURLSessionDataTask), run a check function against the current Artist object and see if all the 3 required elements were there (and if so, make a call to passArtist).

No matter how the finishing order is, it will eventually call the passArtist once it's done fetching 3 elements if you did so.

Here's a simple example to demonstrate the idea in Objective-C (as OP requested):

- (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.
}

This is just one solution. There are many ways to achieve what you wanted once you get the idea.

Cai
  • 3,609
  • 2
  • 19
  • 39
  • i'm sorry, what would the syntax be for that? [session dataTaskWithURL:[NSURL URLWithString:urlString] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error != nil) { NSLog(@"An error occurred: %@", error.localizedDescription); return; } – Sean Calkins Mar 13 '16 at 00:32
  • i guess i failed to mention that this was a project i did in swift and now am doing in objective c. but i've ran into the same issue both times. @Zhi-Wei Cai – Sean Calkins Mar 13 '16 at 00:45
0

Coming back to this 2.5 years later. What I was looking for was completion syntax though at the time I didn't know what that was or how to ask for assistance with it.

func getArtist(artistName: String, completion: (Artist) -> ()) {
     getAlbums(artistIdString)
}

Hopefully, this helps anyone coming across this.

Sean Calkins
  • 312
  • 2
  • 11
-4

First, how are you doing the three API calls, simultaneously? Or the user selects first the artist, then you make a call to get the albums, then you display albums, then user selects an album and you make the third request?

Either ways, I suggest you to write the AsyncTask class inside the Activity class, then you can use a counter to wait for the three calls to finish, then on the onPostExecute() method you can build a Parcelable object and pass it in the bundle (intent.putExtra(authorObject) to receive it in the onCreate method of the second Activity.

Then display the information of the request (i guess you are storing it in a DB for caching)

Isaac Urbina
  • 1,295
  • 11
  • 21