搜尋

首頁  >  問答  >  主體

ios - afnetworking通过for循环发送请求,如何保证接收到数据的顺序和发送请求的顺序一致?

利用AFNetworking进行网络请求,要发送的参数在一个数组里,每次取数组中的一条数据设置参数发送请求,

我通过for循环遍历数组并设置参数发送请求,将网络请求返回的数据添加到一个新的数组中,

发现不是每次请求返回的数据的顺序是一样的,功能需求返回数据的排序必须跟发送请求的顺序是一样的,

求问有什么方法保证前一次请求返回数据之后再发送下一次请求?

非常感谢,万分感谢!!!!

/**
 *  加载订单数据,设置控件位置
 */
- (void)loadOrderData {
        NSString *userID = [[NSUserDefaults standardUserDefaults] stringForKey:@"GOId"];
        NSDictionary *dict = @{
                               @"GOId" : userID,
                               };
        // 将字典转为json
        NSDictionary *params = [ELHOCToJson ocToJson:dict];
        
        NSString *URL = [NSString stringWithFormat:@"%@RealtimeOrder_getROListCon12345.action", ELHBaseURL];
        
        
        __weak typeof(self) weakSelf = self;
        [self.manager POST:URL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            
            weakSelf.ELHOrderArray = [ELHOrderModel mj_objectArrayWithKeyValuesArray:responseObject];
            

            dispatch_queue_t conCurrentQueue = dispatch_queue_create("order", NULL);
            // 获取订单编号
            for (int i = 0; i < weakSelf.ELHOrderArray.count; i++) {
                ELHOrderModel *model = weakSelf.ELHOrderArray[i];
                
                [weakSelf.ELHOrderNumArray addObject:model.ROBM];
                dispatch_barrier_async(conCurrentQueue, ^{
                        // 加载订单详情列表
                        [self loadOrderDetailData:model.ROBM];    // 问题可能就出在这个for循环里,发送请求的顺序应该是按顺序发送的,但是返回数据的时间可能就不一样了,所以造成了数据顺序错乱的问题,求问如何解决此问题?
                    });
            }
            
            
       
            
            // 刷新数据
            [orderVC.tableView reloadData];
            
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%@", error);
        }];
    
}



/**
 *   加载订单详情列表
 */
- (void)loadOrderDetailData:(NSString *)ROBM {
    NSDictionary *dict = @{
                           @"ROBM" : ROBM,
                           };
    
    // 字典转json
    NSDictionary *params = [ELHOCToJson ocToJson:dict];
    
    NSString *URL = [NSString stringWithFormat:@"%@OrderPrice_getOPListByROBM.action", ELHBaseURL];
    
    __weak typeof(self) weakSelf = self;
    [self.manager POST:URL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {       
    
        // 将获取到的订单详情数据逐个添加到数组中
        [weakSelf.ELHOrderDetailArray addObject:[ELHOrderDetailModel mj_objectArrayWithKeyValuesArray:responseObject]];
        ELHOrderTableViewController *orderVC = weakSelf.childViewControllers.firstObject;
        
        orderVC.orderDetailArray = weakSelf.ELHOrderDetailArray;
        
        // 刷新数据
        [orderVC.tableView reloadData];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"%@", error);
    }];
}
阿神阿神2772 天前694

全部回覆(5)我來回復

  • 阿神

    阿神2017-04-17 17:53:19

    我找到了一中折中的辦法,就是在afnetworking的回調裡用dispatch_group_async函數進行順序控制
    程式碼如下:

    [self.manager POST:URL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    //            NSLog(@"%@", responseObject);
                // 字典数组转模型数组
                weakSelf.ELHOrderArray = [ELHOrderModel mj_objectArrayWithKeyValuesArray:responseObject];
    
                
    
                
                // 获取订单编号
                for (int i = 0; i < weakSelf.ELHOrderArray.count; i++) {
                    ELHOrderModel *model = weakSelf.ELHOrderArray[i];
                    
                    // 将订单编号存入一个数组,亦可以不存直接进行获取订单列表操作,加这一步因为项目需求
                    [weakSelf.ELHOrderNumArray addObject:model.ROBM];
                    
    
                }
                
                
                
                /**
                 *  根据上面获取到的订单编号数组,遍历数组 获取 订单列表
                 */
                NSMutableArray *tempArray = [NSMutableArray arrayWithArray:weakSelf.ELHOrderNumArray]; // 创建临时数组用于存放接收到的数据,确保临时数组的长度和你请求到的数据的组数是一样的,这样才能保证你"第几个请求返回的数据放在数组的第几个位置", 这句代码 [tempArray setObject:responseDict atIndexedSubscript:i]; 实现该功能
                if (weakSelf.ELHOrderNumArray != nil) {
                    dispatch_queue_t queue = dispatch_queue_create("order", DISPATCH_QUEUE_CONCURRENT);
                    dispatch_group_t group = dispatch_group_create();
                    
                    for (int i = 0; i < weakSelf.ELHOrderNumArray.count ; i++) {
                        dispatch_group_async(group, queue, ^{
                            NSString *urlStr = [NSString stringWithFormat:@"%@OrderPrice_getOPListByROBM.action", ELHBaseURL];
                            NSURL *url = [NSURL URLWithString:urlStr];
                            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
                            request.HTTPMethod = @"POST";
                            request.HTTPBody = [[NSString stringWithFormat:@"jo={ROBM=%@}", weakSelf.ELHOrderNumArray[i]] dataUsingEncoding:NSUTF8StringEncoding];
                            NSURLResponse *response;
                            NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    
                            NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
                            // 第几个请求返回的数据放在数组的第几个位置
                            [tempArray setObject:responseDict atIndexedSubscript:i];
    
                        });
                    }
                    
                    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
                        // 将所有请求到的数据按顺序放到一个数组中,之后进行别的操作刷新数据就可以了
                        [self.ELHOrderDetailArray addObjectsFromArray:[ELHOrderDetailModel mj_objectArrayWithKeyValuesArray:tempArray]]; 
    
                        ......
                        
                        [self.tableView reloadData];
    
                    });
                    
                }
        
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                NSLog(@"%@", error);
            }];

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 17:53:19

    看了下文件operationQueue 是用來處理delegate 回呼的, NSURLSessionConfigurationHTTPMaximumsPerHost 可以保證同一網域下每次只發起一個請求, 代碼如下:operationQueue 是用来处理 delegate 回调的, NSURLSessionConfigurationHTTPMaximumConnectionsPerHost 可以保证同一域名下每次只发起一个请求, 代码如下:

    NSURLSessionConfiguration *configure = [NSURLSessionConfiguration defaultSessionConfiguration];
    configure.HTTPMaximumConnectionsPerHost = 1;
    
    AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithSessionConfiguration:configure];
    manager.operationQueue.maxConcurrentOperationCount = 1;

    不过 AFNetworking 使用了并行队列 url_session_manager_processing_queue() 处理数据, 由于不能保证这个队列的先后性, 所以其实也不能够确保回调的串行性

    ----------------------------------------原答案-----------------------------
    mangerqueuemaxConcurrentOperationCount 设置成 1.

    还有你这里的 dispatch_barrier_async 我不知道你是想干嘛, 保证串行? 你这个 for rrreee

    不過 AFNetworking 使用了平行佇列 url_session_manager_processing_queue() 處理資料, 由於不能保證這個佇列的先後性, 所以其實也不能夠確保回呼的串列性🎜 🎜----------------------------------------原答案------- ----------------------
    mangerqueuemaxConcurrentOperationCount 設定成1.🎜 🎜還有你這裡的 dispatch_barrier_async 我不知道你是想幹嘛, 保證串行? 你這個 for 循環本來就是串行的啊🎜

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-17 17:53:19

    先把發送佇列掛起,然後for循環產生請求的時候把請求之間加入依賴關係,並放到佇列裡。

    回覆
    0
  • 天蓬老师

    天蓬老师2017-04-17 17:53:19

    這裡還是沒法確定返回資料的順序性的吧,感覺...

    回覆
    0
  • PHP中文网

    PHP中文网2017-04-17 17:53:19

    我也遇到這個問題了 題主解決沒?怎麼弄的

    回覆
    0
  • 取消回覆