AFNetworing同步网络请求?

本文介绍了一种使用系统自带网络请求方法实现同步获取BaseUrl的方案,避免了因主线程阻塞而导致的死锁问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天遇到了一个有关同步网络请求的需求是这样的,App中所有网络请求都需要使用一个BaseUrl作为前缀,这个前缀需要一个专门的配置接口去请求获取。考虑到如果在App启动的时候异步请求配置接口获取BaseUrl,并不能保证APP首页发起的网络请求前缀是正确的BaseUrl,于是我考虑采用同步请求的方法确保BaseUrl的获取。

因为我们在开发App的时候常用的网络框架就是AFNetWorking ,于是我首先想到了使用AFNetworking结合信号量的方式来实现这个同步请求,代码如下:

//更新系统配置,获取BaseUrl的方法,在App启动时候调用
- (void)updateAppSystemConfig{
    //1.创建信号量,阻塞了主线程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //这里省略了AFN请求网络的方法,成功和失败的回调里都需要调用下面的代码
        //2.网络请求结束,发送通知信号
        //dispatch_semaphore_signal(semaphore);
    });
    // 3.发送等待信号
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    //同步请求配置结束之后,结束阻塞
}

但是上述的代码却无形中造成了死锁的问题。这是因为我们使用GCD的信号量首先阻塞了主线程,而且在异步线程里使用了AFN请求网络,由于AFN自身的原因,无论还是成功还是失败网络请求的响应总是要回到主线程中进行操作,但是此时的主线程却是阻塞的,所以就互相等待就造成了死锁。

然后我就采用了系统自带的网络请求的方法来解决这个问题,代码如下:

//更新系统配置,获取BaseUrl的方法,在App启动时候调用
- (void)updateAppSystemConfig{
    //1.创建信号量
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        //开始异步请求操作
        NSURL*url=[NSURL URLWithString:Path_app_config];
        //创建请求命令,并设置缓存策略
        NSURLRequest *request= [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
        //创建会话对象通过单例方法实现
        NSURLSession *session=[NSURLSession sharedSession];
        //执行会话的任务
        NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"请求配置失败了");
            }else{
                NSDictionary *responData=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
                if ([responData[@"errcode"] integerValue] ==QQMFRequest_OK) {
                    //网络请求成功,将新配置更新到本地,可以从配置数据中得到BaseUrl
                    [AppConfigTools updateAppConfigWithData:responData];
                }
            }
            // 2.在网络请求结束后发送通知信号
            dispatch_semaphore_signal(semaphore);
        }];
        //开始执行任务
        [task resume];
    });
    // 3.发送等待信号
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    //同步请求配置结束之后,结束阻塞
}

这里使用的是系统自带的网络请求,请求系统配置BaseUrl的网络请求是在异步线程里实现的,而且网络请求完成之后发出信号量的通知也是在异步线程中,这样就不会造成了阻塞。也实现了同步等待的需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值