Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 大量嵌套完成块的替代方案?_Ios_Swift_Api_Asynchronous_Oauth - Fatal编程技术网

Ios 大量嵌套完成块的替代方案?

Ios 大量嵌套完成块的替代方案?,ios,swift,api,asynchronous,oauth,Ios,Swift,Api,Asynchronous,Oauth,我正在使用OAuthSwift访问goodreads api。首先,我有一个api调用来获取用户id。然后,使用该id,我获取用户在书架上的书籍。然后我检查是否有任何具有特定标题的书籍,如果没有,我再次调用api来创建该书籍。然后,为了确保这本书在那里,我发布了一个进度更新 这是获取用户id的代码: oAuth.client.get( "https://www.goodreads.com/api/auth_user", success: {

我正在使用OAuthSwift访问goodreads api。首先,我有一个api调用来获取用户id。然后,使用该id,我获取用户在书架上的书籍。然后我检查是否有任何具有特定标题的书籍,如果没有,我再次调用api来创建该书籍。然后,为了确保这本书在那里,我发布了一个进度更新

这是获取用户id的代码:

    oAuth.client.get(
        "https://www.goodreads.com/api/auth_user",
        success: {
            data, response in
            // Here I use the returned ID to get the books.
        },
        failure: {
            error in
            //…
        }
    )
一旦我得到了ID,我就需要在下一个api调用中使用它,这将获得书籍。问题是,我不能在第一个调用之后再添加下一个调用,因为它们是异步的,所以第二个调用将在我从第一个调用获得ID之前启动

那么,我要做的是在成功闭包中添加第二个api调用,我在代码中用注释指出了它。所以我有两段非常相似的代码,一段在另一段内部;当第一个api调用成功时,它将调用下一个api调用。但是我必须使用第二次调用的结果来决定是否添加一本新书。所以我有第三个api调用,将书添加到第二个调用的成功块中,也就是第一个调用的成功块中……您可以看到事情开始变得非常混乱。它甚至不止于此:我有第四个api调用来发布状态更新,它在第三个调用的完成处理程序中,第二个调用的完成处理程序中,第一个调用的完成处理程序中

那么…我应该做什么来代替这个呢?如果这是一个愚蠢的问题,我很抱歉,但我对swift和编程都是新手。

我认为苹果已经提供了使用GCD处理这种情况的最佳方法,GCD提供了串行队列,以串行方式执行块/API。这是先进先出的顺序

输出:


我还没有深入了解GCD,对于您的场景,我可以建议您在real quick中使用下面的完成块调用每个API,这是我现在可以帮助您的

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(backgroundQueue, ^{

    [self callGetUserIdAPIAndCompletion:^(NSDictionary *dictResponse)     {

        [self callGetBooksAPIForUserId:dictResponse[@"userId"] AndCompletion:^(NSDictionary *dictResponse) {

            [self callAddBookAPIForUserId:dictResponse[@"userId"] bookId:dictResponse[@"bookId"] AndCompletion:^(NSDictionary *dictResponse) {

                [self callPostStatusUpdateAPIForUserId:dictResponse[@"userId"] status:@"status" AndCompletion:^(NSDictionary *dictResponse) {

                }];
            }];
        }];
    }];
});
并编写API调用函数,如下所示

-(void)callGetUserIdAPIAndCompletion:(void(^)(NSDictionary *dictResponse))completion {

    NSDictionary *dictResponse;

    //Call First API
    NSLog(@"API 1 completes");
    completion(dictResponse);
}

-(void)callGetBooksAPIForUserId:(NSString*)userId AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

    NSDictionary *dictResponse;

    //Call Second API with userId
    NSLog(@"API 2 completes");
    completion(dictResponse);
}

-(void)callAddBookAPIForUserId:(NSString*)userId bookId:(NSString*)bookId AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

     NSDictionary *dictResponse;

     //Call Third API with userId and bookId
     NSLog(@"API 3 completes");
     completion(dictResponse);
}

-(void)callPostStatusUpdateAPIForUserId:(NSString*) userId status:(NSString*) status AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

     NSDictionary *dictResponse;

     //Call Fourth API with userId and status
     NSLog(@"API 4 completes");
     completion(dictResponse);
}

您可以使用PromiseKit,您可以将呼叫包装在NSO操作中,并将其放入串行NSOperationQueue@Paul哇,看起来很有希望。看到我在那里做了什么吗?我会调查的,谢谢@更具体地说,nsurlsession不被视为操作。OP显然是在使用Alamofire或similarPromise工具包,而dispatch_组是一种减少嵌套块丑陋的方法。如果调用是异步方法(如网络调用),则通过这种方式链接的只是请求的开始,而不是响应Hello。问题标记为swift,请以swift而不是其他语言提供答案。谢谢
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(backgroundQueue, ^{

    [self callGetUserIdAPIAndCompletion:^(NSDictionary *dictResponse)     {

        [self callGetBooksAPIForUserId:dictResponse[@"userId"] AndCompletion:^(NSDictionary *dictResponse) {

            [self callAddBookAPIForUserId:dictResponse[@"userId"] bookId:dictResponse[@"bookId"] AndCompletion:^(NSDictionary *dictResponse) {

                [self callPostStatusUpdateAPIForUserId:dictResponse[@"userId"] status:@"status" AndCompletion:^(NSDictionary *dictResponse) {

                }];
            }];
        }];
    }];
});
-(void)callGetUserIdAPIAndCompletion:(void(^)(NSDictionary *dictResponse))completion {

    NSDictionary *dictResponse;

    //Call First API
    NSLog(@"API 1 completes");
    completion(dictResponse);
}

-(void)callGetBooksAPIForUserId:(NSString*)userId AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

    NSDictionary *dictResponse;

    //Call Second API with userId
    NSLog(@"API 2 completes");
    completion(dictResponse);
}

-(void)callAddBookAPIForUserId:(NSString*)userId bookId:(NSString*)bookId AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

     NSDictionary *dictResponse;

     //Call Third API with userId and bookId
     NSLog(@"API 3 completes");
     completion(dictResponse);
}

-(void)callPostStatusUpdateAPIForUserId:(NSString*) userId status:(NSString*) status AndCompletion:(void(^)(NSDictionary *dictResponse))completion {

     NSDictionary *dictResponse;

     //Call Fourth API with userId and status
     NSLog(@"API 4 completes");
     completion(dictResponse);
}