MST
星途 面试题库

面试题:Objective-C之AFNetworking源码中的请求队列管理

AFNetworking中是如何管理网络请求队列的?请分析AFURLSessionManager类中与请求队列相关的核心代码逻辑,包括如何处理请求的添加、暂停、取消等操作,以及这些操作在多线程环境下的线程安全是如何保证的?
40.1万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

AFNetworking 网络请求队列管理

  1. AFURLSessionManager 简介
    • AFURLSessionManager 是 AFNetworking 中负责管理 NSURLSession 相关操作的类,它在网络请求队列管理方面起着关键作用。
  2. 核心代码逻辑 - 请求添加
    • AFURLSessionManager 通过 dataTaskWithRequest:completionHandler: 等方法创建 NSURLSessionDataTask 等任务。例如:
    - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                            completionHandler:(void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler {
        __block NSURLSessionDataTask *dataTask = nil;
        dataTask = [self.session dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseData, NSError * _Nullable error) {
            [self URLSession:self.session task:dataTask didCompleteWithError:error];
            if (completionHandler) {
                completionHandler(response, responseData, error);
            }
        }];
        return dataTask;
    }
    
    • 这里创建了一个 NSURLSessionDataTask,并将其与特定的请求和完成处理程序关联。当调用 resume 方法时,任务会被添加到 NSURLSession 的请求队列中执行。
  3. 核心代码逻辑 - 请求暂停
    • AFURLSessionManager 中的任务(如 NSURLSessionDataTask)本身有 suspend 方法。例如,当我们有一个 NSURLSessionDataTask 实例 task 时,可以调用 [task suspend] 暂停任务。
    • AFURLSessionManager 层面,它会跟踪任务的状态。例如,如果要暂停所有任务,可以遍历所有任务并调用其 suspend 方法。虽然 AFNetworking 没有直接提供暂停所有任务的公开便捷方法,但理论上可以通过遍历 tasks 数组(NSURLSession 有方法获取其管理的任务数组)来实现。
  4. 核心代码逻辑 - 请求取消
    • 同样,NSURLSessionDataTaskcancel 方法,如 [task cancel]AFURLSessionManager 会在任务取消时进行相应处理,例如在 URLSession:task:didCompleteWithError: 方法中,当错误的 code 表示任务取消时,会进行一些清理和通知操作。
    • 例如:
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
        if (error && error.code == NSURLErrorCancelled) {
            // 处理任务取消相关逻辑,如通知 delegate 等
        }
        // 其他任务完成处理逻辑
    }
    
  5. 线程安全保证
    • 使用 GCD:AFNetworking 大量使用 Grand Central Dispatch(GCD)来处理多线程问题。例如,在更新任务状态、通知 delegate 等操作时,会在主队列或特定的队列中执行。比如在 URLSession:task:didCompleteWithError: 方法中,通知 delegate 的操作会在主队列中执行,以确保 UI 更新等操作的线程安全。
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self.delegate respondsToSelector:@selector(afURLSessionManager:task:didCompleteWithError:)]) {
            [self.delegate afURLSessionManager:self task:task didCompleteWithError:error];
        }
    });
    
    • 锁机制:在一些需要保护共享资源(如任务状态的跟踪数据结构)的地方,可能会使用锁机制。虽然 AFNetworking 源码中没有大量显式使用 NSLock 等传统锁,但通过 GCD 的队列同步机制,同样可以达到保护共享资源的目的。例如,对任务状态的更新操作可能在一个特定的串行队列中执行,避免多个线程同时修改导致数据不一致。