面试题答案
一键面试优化方面及策略
- 请求队列管理:
- 建立请求队列,根据请求优先级进行排序。例如,对于用户当前操作相关的请求(如登录、支付)设置高优先级,其他如数据预加载等设置低优先级。这样在网络资源有限时,优先处理重要请求。
- 使用NSOperationQueue来管理请求任务,通过设置maxConcurrentOperationCount控制并发请求数量,避免过多请求耗尽网络资源。比如在弱网环境下,将并发数设置为1 - 2个,保证每个请求都能有足够的带宽。
- 数据压缩:
- 在发送请求前,对请求数据进行压缩。可以使用zlib等压缩库,将数据压缩后再通过网络传输。例如,对于一些包含大量文本的请求,压缩后能显著减少传输数据量,加快请求速度。
- 服务器端也要相应支持解压缩,在接收到压缩数据后进行解压处理。
- 缓存机制:
- 利用NSURLCache进行缓存管理。对于一些不经常变化的数据请求(如APP配置信息、商品分类等),设置合适的缓存策略,如NSURLRequestUseProtocolCachePolicy,让系统根据HTTP协议头中的缓存控制信息来决定是否使用缓存。
- 对于自定义的缓存,可以使用NSUserDefaults或文件系统来存储缓存数据。例如,将一些本地频繁使用的配置数据以plist文件形式缓存到文件系统中,下次请求时先检查缓存是否存在且有效,若有效则直接使用缓存数据,减少网络请求。
- 网络检测与自适应:
- 使用Reachability类检测网络状态。实时监测网络连接情况,当网络状态发生变化(如从WiFi切换到蜂窝网络,或网络从可用变为不可用)时,及时调整网络请求策略。比如在弱网下,降低请求频率,减少并发请求数量。
- 根据网络速度自适应调整请求内容。例如,在低速网络下,只请求必要的关键数据,避免请求大量图片或视频等大文件。
请求超时处理
- 设置合理超时时间:
- 在创建NSURLRequest时,通过设置timeoutInterval属性来指定请求超时时间。一般来说,对于普通的HTTP请求,可以设置超时时间为15 - 30秒。例如:
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
- 超时处理逻辑:
- 使用NSURLSession的代理方法处理超时情况。当请求超时时,会调用
URLSession:task:didCompleteWithError:
代理方法,在该方法中判断错误类型,如果是超时错误(NSError
的code
为NSURLErrorTimedOut
),则提示用户网络超时,并根据业务需求决定是否重新发起请求。例如:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error && error.code == NSURLErrorTimedOut) { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"网络超时" message:@"请检查网络连接并重试" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]; [alertController addAction:okAction]; [self presentViewController:alertController animated:YES completion:nil]; } }
- 使用NSURLSession的代理方法处理超时情况。当请求超时时,会调用
断点续传处理
- 支持断点续传的服务器:服务器端需要支持断点续传功能,一般通过HTTP协议的
Range
头字段来实现。当客户端请求下载文件时,服务器返回文件的Content - Length
等信息。 - 客户端实现:
- 使用NSURLSessionDownloadTask进行下载任务。在下载过程中,记录已下载的字节数。当下载中断(如网络切换、应用进入后台等)时,保存已下载的字节数。
- 重新发起下载请求时,在NSURLRequest中设置
Range
头字段,指定从上次中断的位置继续下载。例如:
long long resumeOffset = 0; // 已下载的字节数 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSString *range = [NSString stringWithFormat:@"bytes=%lld -", resumeOffset]; [request setValue:range forHTTPHeaderField:@"Range"]; NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
重连机制处理
- 自动重连策略:
- 在请求失败(除了用户主动取消请求外)时,设置一个重连次数和重连间隔时间。例如,设置最多重连3次,每次重连间隔时间从1秒开始,每次重连间隔时间翻倍(1秒、2秒、4秒)。
- 使用一个计数器记录重连次数,在请求失败的代理方法中判断是否达到最大重连次数,如果未达到,则延迟相应时间后重新发起请求。例如:
@interface ViewController () { NSInteger retryCount; } @end @implementation ViewController - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error && error.code != NSURLErrorCancelled) { if (retryCount < 3) { NSTimeInterval delay = pow(2, retryCount); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self startRequest]; // 重新发起请求的方法 retryCount++; }); } else { // 提示用户请求失败,达到最大重连次数 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"请求失败" message:@"达到最大重连次数,请检查网络" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]; [alertController addAction:okAction]; [self presentViewController:alertController animated:YES completion:nil]; } } } @end
- 网络状态检测重连:结合网络检测机制,当网络从不可用变为可用时,自动重连之前失败的请求。在网络状态变化的回调方法中,重新发起之前失败的请求任务。