MST

星途 面试题库

面试题:Objective-C异步网络请求并发控制下的复杂场景处理

在一个Objective-C开发的应用中,存在多个不同优先级的异步网络请求任务,并且有些任务依赖于其他任务的完成结果。同时,为了节省资源,当应用进入后台时需要暂停部分非关键请求,恢复前台时继续执行。请设计一个全面的并发控制方案,详细说明使用的技术、数据结构以及关键代码逻辑。
36.1万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

技术选择

  1. Grand Central Dispatch (GCD):GCD 是苹果公司为多核的并行运算提出的解决方案,它基于队列(queue)来管理任务,能够方便地实现异步任务和并发控制。
  2. NSOperationQueue:NSOperationQueue 是基于操作(NSOperation)的任务管理队列,NSOperation 是一个抽象类,它的子类包括 NSInvocationOperation 和 NSBlockOperation,还可以自定义子类。可以设置操作之间的依赖关系,并且可以控制队列的最大并发数。

数据结构

  1. NSMutableDictionary:用于存储不同优先级的请求任务,以优先级作为 key,以 NSMutableArray 作为 value 存储对应的请求任务。例如:
@property (nonatomic, strong) NSMutableDictionary<NSNumber *, NSMutableArray<NSOperation *> *> *priorityOperationDict;
  1. NSMutableArray:在 NSMutableDictionary 中作为 value,存储相同优先级的请求任务。

关键代码逻辑

  1. 创建任务及添加到队列
// 创建一个 NSBlockOperation
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    // 网络请求代码
    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:@"http://example.com"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 处理请求结果
    }];
    [task resume];
}];

// 假设设置优先级为1
NSNumber *priorityNumber = @1;
if (!self.priorityOperationDict[priorityNumber]) {
    self.priorityOperationDict[priorityNumber] = [NSMutableArray array];
}
[self.priorityOperationDict[priorityNumber] addObject:operation];
  1. 设置任务依赖关系
NSBlockOperation *dependencyOperation = [NSBlockOperation blockOperationWithBlock:^{
    // 前置任务代码
}];
NSBlockOperation *dependentOperation = [NSBlockOperation blockOperationWithBlock:^{
    // 依赖于前置任务的代码
}];
[dependentOperation addDependency:dependencyOperation];
  1. 将任务添加到队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 设置队列的最大并发数
queue.maxConcurrentOperationCount = 3; 

// 假设从 priorityOperationDict 中获取优先级为1的任务数组
NSArray<NSOperation *> *operations = self.priorityOperationDict[@1];
[queue addOperations:operations waitUntilFinished:NO];
  1. 应用进入后台和前台处理
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];

- (void)handleEnterBackground {
    // 暂停非关键请求,例如优先级低的任务
    NSArray<NSOperation *> *lowPriorityOperations = self.priorityOperationDict[@0];
    for (NSOperation *operation in lowPriorityOperations) {
        [operation cancel];
    }
}

- (void)handleEnterForeground {
    // 恢复暂停的任务,重新创建并添加到队列
    NSArray<NSOperation *> *lowPriorityOperations = self.priorityOperationDict[@0];
    for (NSOperation *operation in lowPriorityOperations) {
        if (operation.isCancelled) {
            NSBlockOperation *newOperation = [NSBlockOperation blockOperationWithBlock:^{
                // 重复网络请求代码
            }];
            [self.priorityOperationDict[@0] addObject:newOperation];
            [[NSOperationQueue new] addOperation:newOperation];
        }
    }
}

通过以上方案,使用 GCD 和 NSOperationQueue 结合合适的数据结构,能够实现对不同优先级异步网络请求任务的并发控制,并处理应用进入后台和前台时的任务管理。