如何等待异步调用完成

时间:2016-03-12 22:47:39

标签: ios objective-c swift nsurlsessiondatatask

我正在使用 Spotify API 运行三个API调用,以获取以下数据并将其存储到我的Artist对象中:

  1. 艺术家。
  2. 那位艺术家的专辑。
  3. 艺术家每张专辑的曲目。
  4. 完成后,我想将对象传递给另一个视图控制器。它看起来像这样:(如果有必要,可以在那里发布所有NSURLSession代码)

    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
    }
    

3 个答案:

答案 0 :(得分:0)

NSURLSession(或NSURLSessionDataTask)的回调函数/块(或Apple术语中的完成处理程序)中,对当前运行检查函数Artist对象并查看是否所有3个必需元素都存在(如果是,请拨打passArtist)。

无论整理顺序如何,如果您完成了此操作,它最终会在passArtist完成后调用3个元素。

以下是在 Objective-C (请求OP)中演示该想法的简单示例:

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

这只是一个解决方案。一旦你明白了,有很多方法可以实现你想要的东西。

答案 1 :(得分:0)

回到2.5年后。我一直在寻找的是补全语法,尽管当时我不知道这是什么,也不知道如何寻求帮助。

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

希望这能帮助遇到此问题的任何人。

答案 2 :(得分:-4)

首先,你是如何同时进行三个API调用的? 或者用户首先选择艺术家,然后拨打电话获取相册,然后显示相册,然后用户选择相册并发出第三个请求?

无论哪种方式,我建议你在Activity类中编写AsyncTask类,然后你可以使用计数器等待三次调用完成,然后在onPostExecute()方法中你可以构建一个Parcelable对象并传递它在bundle(intent.putExtra(authorObject)中,在第二个Activity的onCreate方法中接收它。

然后显示请求的信息(我猜你将它存储在数据库中用于缓存)