Ios 阿拉莫菲尔-如何处理完成块?

Ios 阿拉莫菲尔-如何处理完成块?,ios,swift,alamofire,Ios,Swift,Alamofire,我对iOS非常陌生,想要并使用Alamofire。我想问以下问题:当所有项目(在我的例子中是用户)都已处理时,如何调用一些完成块。完成块位于延迟块中 StopsHandler.swift func requestStopsForUser(user: User, completion: (result: RequestResult, json: JSON?) -> Void) { alamofireManager?.request(.GET, "\(AppSettings.ApiUR

我对iOS非常陌生,想要并使用Alamofire。我想问以下问题:当所有项目(在我的例子中是用户)都已处理时,如何调用一些完成块。完成块位于延迟块中

StopsHandler.swift

func requestStopsForUser(user: User, completion: (result: RequestResult, json: JSON?) -> Void) {
    alamofireManager?.request(.GET, "\(AppSettings.ApiURL)/v1/users/\(user.id)/stops.json", headers: ["Authorization": "Token token=\(user.apiKey)"]).responseJSON { response in
        switch response.result {
        case .Success:
            if let value = response.result.value {
                completion(result: .Success, json: JSON(value))
            }
        case .Failure(let error):
            if error.code == NSURLErrorTimedOut {
                completion(result: .TimedOut, json: nil)
            } else {
                completion(result: .ConnectionFailed, json: nil)
            }
        }
    }
}
func fetchUsersAndStops(completion: (result: RequestResult) -> Void ) {

    var allStopsToWrite = [[Stop]]() //for each user we have array of stops to write in model

    requestAllUsers() { result, json in
        switch result {
        case .Success:
            let users = self.usersFromJSON(json)

            for (i, user) in users.enumerate() {   
                StopsHandler.sharedInstance.requestStopsForUser(user) { result, json in
                    print("i in = \(i)")
                    switch result {
                    case .Success:
                        defer {
                            let isLastUser = (i == users.count - 1)
                            if isLastUser {
                                try! self.realm.write(transactionBlock: {
                                    for (index, stopsToWrite) in allStopsToWrite.enumerate() {
                                        users[index].stops.appendContentsOf(stopsToWrite)
                                        self.realm.add(users[index], update: true)
                                    }},
                                    completion: {
                                        completion(result: .Success) //I want to call this completion when last user is already handled.
                                })
                            }
                        }

                        guard let json = json else {return}
                        let stops = StopsHandler.sharedInstance.stopsFromJSON(json)

                        let globalStops = self.realm.objects(Stop)

                        var stopsToWrite = [Stop]()

                        for stop in stops {
                            if globalStops.filter("id = '\(stop.id)'").first == nil {
                                stopsToWrite.append(stop)
                                if let currentUserId = self.currentUser?.id {
                                    if currentUserId == user.id {
                                        user.loggedIn = true
                                    }
                                }
                            }
                        }
                        allStopsToWrite.append(stopsToWrite)
                    case .TimedOut:
                        completion(result: .TimedOut)
                    case .ConnectionFailed:
                        completion(result: .ConnectionFailed)
                    }
                }
            }
        case .TimedOut:
            completion(result: .TimedOut)
        case .ConnectionFailed:
            completion(result: .ConnectionFailed)
        }
    }
}
Main.swift

func requestStopsForUser(user: User, completion: (result: RequestResult, json: JSON?) -> Void) {
    alamofireManager?.request(.GET, "\(AppSettings.ApiURL)/v1/users/\(user.id)/stops.json", headers: ["Authorization": "Token token=\(user.apiKey)"]).responseJSON { response in
        switch response.result {
        case .Success:
            if let value = response.result.value {
                completion(result: .Success, json: JSON(value))
            }
        case .Failure(let error):
            if error.code == NSURLErrorTimedOut {
                completion(result: .TimedOut, json: nil)
            } else {
                completion(result: .ConnectionFailed, json: nil)
            }
        }
    }
}
func fetchUsersAndStops(completion: (result: RequestResult) -> Void ) {

    var allStopsToWrite = [[Stop]]() //for each user we have array of stops to write in model

    requestAllUsers() { result, json in
        switch result {
        case .Success:
            let users = self.usersFromJSON(json)

            for (i, user) in users.enumerate() {   
                StopsHandler.sharedInstance.requestStopsForUser(user) { result, json in
                    print("i in = \(i)")
                    switch result {
                    case .Success:
                        defer {
                            let isLastUser = (i == users.count - 1)
                            if isLastUser {
                                try! self.realm.write(transactionBlock: {
                                    for (index, stopsToWrite) in allStopsToWrite.enumerate() {
                                        users[index].stops.appendContentsOf(stopsToWrite)
                                        self.realm.add(users[index], update: true)
                                    }},
                                    completion: {
                                        completion(result: .Success) //I want to call this completion when last user is already handled.
                                })
                            }
                        }

                        guard let json = json else {return}
                        let stops = StopsHandler.sharedInstance.stopsFromJSON(json)

                        let globalStops = self.realm.objects(Stop)

                        var stopsToWrite = [Stop]()

                        for stop in stops {
                            if globalStops.filter("id = '\(stop.id)'").first == nil {
                                stopsToWrite.append(stop)
                                if let currentUserId = self.currentUser?.id {
                                    if currentUserId == user.id {
                                        user.loggedIn = true
                                    }
                                }
                            }
                        }
                        allStopsToWrite.append(stopsToWrite)
                    case .TimedOut:
                        completion(result: .TimedOut)
                    case .ConnectionFailed:
                        completion(result: .ConnectionFailed)
                    }
                }
            }
        case .TimedOut:
            completion(result: .TimedOut)
        case .ConnectionFailed:
            completion(result: .ConnectionFailed)
        }
    }
}
我假设我的代码在
main_queue
中运行,我希望输出如下(服务器上有4个用户):

但突然我有了以下几点:

i in = 3
i in = 1
i in = 2
i in = 0

我不知道为什么。非常感谢您的帮助!提前谢谢

Alamofire.request
未在主队列上运行。它异步运行
,但默认情况下,
主队列上的
.responseJSON
将返回以允许您更新UI。因此,您的输出不是您所期望的

如果希望它按顺序返回,则必须将请求包装在调度主队列中

大概是这样的:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(0.2) * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
    // your code here.
})

Alamofire.request
未在主队列上运行。它异步运行
,但默认情况下,
主队列上的
.responseJSON
将返回以允许您更新UI。因此,您的输出不是您所期望的

如果希望它按顺序返回,则必须将请求包装在调度主队列中

大概是这样的:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(Double(0.2) * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
    // your code here.
})

因为Alarmofire正在异步方法中调用请求。这就是为什么所有的请求都是一次调用的,但是对于所有的请求,响应时间都不一样

若要按顺序调用所有请求,可以在前一个服务完成后调用服务

由于我们面临同样的问题,所以我们确实使用了调度块来执行序列任务

- (void)fetchAllUserAndStopWithCompletion:(void(^)(id resultResponse, BOOL isComplete))completion {

  // Step 1: Define default parameters and limits.
  __block NSInteger totalNumberOfUser = 4;
  __block NSInteger currentRequest = 0;
  __block dispatch_block_t t_request;

dispatch_block_t request = [^{
    // Step 2: Fetch User information for currentRequest id.
    [UserRequest fetchUserRequestWithId:<UserId or Any Unique Id>
                           successBlock:^(id resultResponse, NSError *error) {

                               currentRequest += 1;
                               // Step 3: Check for remaining request. If request is remaining then call ’t_request()’.
                               if (currentRequest < totalNumberOfUser) {
                                   // Request Remaining
                                   if (completion) {
                                       id response = (!error)?resultResponse:nil;
                                       completion(response, NO);
                                   }
                                   t_request();
                               }
                               else {
                                   // All Request Completed
                                   if (completion) {
                                       id response = (!error)?resultResponse:nil;
                                       completion(response, YES);
                                   }
                               }
                           }];

} copy];

t_request = request;
request();
}
-(void)fetchAllUserAndStopWithCompletion:(void(^)(id resultResponse,BOOL isComplete))完成{
//步骤1:定义默认参数和限制。
__块NSInteger totalNumberOfUser=4;
__块NSInteger currentRequest=0;
__阻塞调度请求;
调度阻止请求=[^{
//步骤2:获取currentRequest id的用户信息。
[UserRequest fetchUserRequestWithId:
successBlock:^(id resultResponse,N错误*错误){
currentRequest+=1;
//步骤3:检查剩余请求。如果请求剩余,则调用“t_request()”。
if(currentRequest
注意:这仅在您使用不同的调用获取每个用户信息时才有帮助。如果在一次调用中获得所有用户信息,则只需使用NSSortDescriptor对用户进行排序


如果您在执行序列任务时遇到任何问题,可以在下面留下评论。

因为Alarmofire正在异步方法中调用请求。这就是为什么所有的请求都是一次调用的,但是对于所有的请求,响应时间都不一样

若要按顺序调用所有请求,可以在前一个服务完成后调用服务

由于我们面临同样的问题,所以我们确实使用了调度块来执行序列任务

- (void)fetchAllUserAndStopWithCompletion:(void(^)(id resultResponse, BOOL isComplete))completion {

  // Step 1: Define default parameters and limits.
  __block NSInteger totalNumberOfUser = 4;
  __block NSInteger currentRequest = 0;
  __block dispatch_block_t t_request;

dispatch_block_t request = [^{
    // Step 2: Fetch User information for currentRequest id.
    [UserRequest fetchUserRequestWithId:<UserId or Any Unique Id>
                           successBlock:^(id resultResponse, NSError *error) {

                               currentRequest += 1;
                               // Step 3: Check for remaining request. If request is remaining then call ’t_request()’.
                               if (currentRequest < totalNumberOfUser) {
                                   // Request Remaining
                                   if (completion) {
                                       id response = (!error)?resultResponse:nil;
                                       completion(response, NO);
                                   }
                                   t_request();
                               }
                               else {
                                   // All Request Completed
                                   if (completion) {
                                       id response = (!error)?resultResponse:nil;
                                       completion(response, YES);
                                   }
                               }
                           }];

} copy];

t_request = request;
request();
}
-(void)fetchAllUserAndStopWithCompletion:(void(^)(id resultResponse,BOOL isComplete))完成{
//步骤1:定义默认参数和限制。
__块NSInteger totalNumberOfUser=4;
__块NSInteger currentRequest=0;
__阻塞调度请求;
调度阻止请求=[^{
//步骤2:获取currentRequest id的用户信息。
[UserRequest fetchUserRequestWithId:
successBlock:^(id resultResponse,N错误*错误){
currentRequest+=1;
//步骤3:检查剩余请求。如果请求剩余,则调用“t_request()”。
if(currentRequest
注意:这仅在您使用不同的调用获取每个用户信息时才有帮助。如果在一次调用中获得所有用户信息,则只需使用NSSortDescriptor对用户进行排序


如果您在执行序列任务方面有任何问题,您可以在下面留下评论。

您有4个用户,因此您调用了4次请求,并且在检索到所有4个用户后您想做些什么,这就是您的问题吗?很不清楚你想问什么really@Tj3n是的,没错,我想做点什么