[转载]AFNtworking同步请求解决方法

很多时候我们在做网络请求的时候,往往要拿到数据后才能去处理进一步的操作。但是,AFNetworking
并没有同步的方法,那么我们应该怎么处理呢?

方法一:


- (void)getWeatherData
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer     = [AFJSONRequestSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];

        __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
        __block BOOL isSuccess           = NO;
        __block NSDictionary *json       = nil;

        [manager GET:@"http://www.weather.com.cn/data/sk/101010100.html"
          parameters:nil
             success:^(NSURLSessionDataTask *task, id responseObject)
        {
            NSLog(@"加载成功 %@",responseObject);

            isSuccess = YES;

            if ([responseObject isKindOfClass:[NSDictionary class]]) {
                json = responseObject;
            }

            dispatch_semaphore_signal(sem);

        } failure:^(NSURLSessionDataTask *task, NSError *error) {

            NSLog(@"加载失败 %@",error);

            isSuccess = NO;

            dispatch_semaphore_signal(sem);
        }];

        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);

        dispatch_async(dispatch_get_main_queue(), ^{

            /* 回到主线程做进一步处理 */

            if(isSuccess) {

                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"请求成功" message:[NSString stringWithFormat:@"%@",json] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alert show];
            }
        });
    });
}

方法二:


- (void)getWeatherData
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        NSCondition *condition = [[NSCondition alloc] init];

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer     = [AFJSONRequestSerializer serializer];
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];

        __block BOOL isSuccess           = NO;
        __block NSDictionary *json       = nil;

        [manager GET:@"http://www.weather.com.cn/data/sk/101010100.html"
          parameters:nil
             success:^(NSURLSessionDataTask *task, id responseObject)
         {
             NSLog(@"加载成功 %@",responseObject);

             isSuccess = YES;

             if ([responseObject isKindOfClass:[NSDictionary class]]) {
                 json = responseObject;
             }

             [condition lock];
             [condition signal];
             [condition unlock];

         } failure:^(NSURLSessionDataTask *task, NSError *error) {

             NSLog(@"加载失败 %@",error);

             isSuccess = NO;

             [condition lock];
             [condition signal];
             [condition unlock];
         }];

        [condition lock];
        [condition wait];
        [condition unlock];

        dispatch_async(dispatch_get_main_queue(), ^{

            /* 回到主线程做进一步处理 */

            if(isSuccess) {

                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"请求成功" message:[NSString stringWithFormat:@"%@",json] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [alert show];
            }
        });
    });
}

方法三:


- (NSDictionary *)getJsonData
{
    NSString *url = [NSString stringWithFormat:@"请求的url字符串"];

    /* 请求参数字典 */
    NSMutableDictionary *requestParms = [[NSMutableDictionary alloc] init];
    [requestParms setObject:@"value" forKey:@"key"];

    AFJSONRequestSerializer *requestSerializer = [AFJSONRequestSerializer serializer];
    NSMutableURLRequest *request = [requestSerializer requestWithMethod:@"POST" URLString:url parameters:requestParms error:nil];

    /* 最终继承自 NSOperation,看到这个,大家可能就知道了怎么实现同步的了,也就是利用 NSOperation 来做的同步请求 */
    AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    AFHTTPResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializer];

    [requestOperation setResponseSerializer:responseSerializer];

    [requestOperation start];

    [requestOperation waitUntilFinished];

    /* 请求结果 */
    NSDictionary *result = (NSDictionary *)[requestOperation responseObject];

    if (result != nil) {

        return result;
    }
    return nil;
}


小结

使用上面任意一种方法都可以解决AFNetworking同步请求的操作。需要注意的是,前两种方法中请求要放在异步线程执行,否则会死锁,在请求结束后再回到主线程执行。

上半部分内容转载自:AFNtworking同步请求解决方法
作者:jixuqianxing

Postscript:

  • 使用AFNetworking时,程序会先执行网络请求,后直接往前走到方法的return,在之后才会执行完block内部的内容,故而需要方法的返回值时需慎重;
  • 第一种阻塞线程实现网络请求同步的做法测试了下发现无效,分析原因可能为先进行网络请求,然后直接执行到dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);,此时未接收到dispatch_semaphore_signal(sem);的信息,而当该语句执行的时候该方法已经运行结束,故无法接着执行return操作
  • 后面方法未测,目前先采用同步网络请求进行操作,后面有时间再行测试
  • 如有遗漏错误之处欢迎指正

你可能感兴趣的:([转载]AFNtworking同步请求解决方法)