资讯动态

iOS: 网络请求再学习

发布时间:2026/8/12 18:59:00 来源:尧图企业网站定制
文章目录网络请求再学习网络请求的步骤创建请求地址创建请求类完整步骤 (显式创建)创建会话1. 共享单例会话2. 基于配置的会话无代理仅闭包回调3. 基于配置 自定义代理全功能模式生成任务任务的类型任务的回调方式任务的创建方式启动任务网络请求再学习网络请求的步骤创建请求地址确定接口地址处理路径和查询参数如?keyxxxcitybeijing。创建请求类创建会话配置会话创建NSURLSessionConfiguration设置超时时间、缓存策略、是否允许蜂窝网络等。这一步决定了网络请求的“基调”默认、临时、后台。创建会话利用上一步的配置生成NSURLSession实例。如果不需要代理监听如进度直接用[NSURLSession sharedSession]即可。生成任务根据业务需求选择任务类型DataTask/DownloadTask/UploadTask并传入 URL 或 Request 对象。此时任务处于suspended挂起状态还未开始联网。启动任务调用[task resume]处理响应数据如果自定义了delegate且会话不再使用需调用[session finishTasksAndInvalidate]或[session invalidateAndCancel]来打破session对delegate的强引用。清理会话创建请求地址在开始学习的时候, 我们创建URL一般是直接使用字符串, 这种方式只适合静态地址 (没有中文, 没有空格, 没有特殊符号)NSURL *url [NSURL URLWithString:https://api.weatherapi.com/v1/forecast.json];创建请求类在NSURLSession中苹果提供了一个非常便捷的方法-(NSURLSessionDataTask*)dataTaskWithURL:(NSURL*)url;如果你直接传入URL系统会在内部自动帮你创建一个默认的NSURLRequest默认使用GET方法默认超时时间默认缓存策略。在这种情况下不需要写NSURLRequest的代码任务就直接生成了通过这种方式直接生成任务就不用去专门创建请求类了完整步骤 (显式创建)如果请求稍微复杂一点比如POST请求、需要加Headers如 Token、需要上传Body数据你就必须显式地创建NSMutableURLRequest。// 创建请求类NSMutableURLRequest*request[NSMutableURLRequest requestWithURL:url];// HTTP 方法request.HTTPMethodGET;// 时间阈值request.timeoutInterval15;创建会话在iOS中, 创建会话共有3种方式,分别对应不同的业务复杂度1. 共享单例会话直接使用系统提供的全局单例对象。NSURLSession *session [NSURLSession sharedSession];适用场景简单的、一次性的 GET/POST 请求且不需要监听上传/下载进度。特点使用系统默认配置类似浏览器无法自定义超时时间、缓存策略且无法设置 Delegate。所有回调只能通过completionHandler闭包处理。内存管理无需管理它是个单例App 生命周期内一直存在。2. 基于配置的会话无代理仅闭包回调使用NSURLSessionConfiguration来创建但不设置代理传入nil所有的数据返回都靠 Block 闭包。NSURLSessionConfiguration *config [NSURLSessionConfiguration defaultSessionConfiguration]; config.timeoutIntervalForRequest 30.0; // 注意delegate 传 nildelegateQueue 传 nil 或主队列 NSURLSession *session [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];适用场景需要自定义超时、缓存策略或额外 Headers但不需要监听进度如普通的 JSON 接口请求。特点灵活度高于sharedSession但由于没有 Delegate无法处理需要身份验证如客户端证书或重定向的复杂场景。内存管理因为delegate是nil不存在循环引用问题会话用完后系统会自动释放通常不需要手动 invalidate。NSURLSession* session [NSURLSession sessionWithConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration]];相当于NSURLSessionConfiguration*config[NSURLSessionConfiguration defaultSessionConfiguration];NSURLSession*session[NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];方法的第三个参数delegateQueue指的是回调队列含义指定所有代理方法以及completionHandler闭包在哪个线程执行。作用传入主队列Main Queue意味着回调闭包会在主线程执行。虽然delegate传的是nil但这个delegateQueue依然有效。当使用带completionHandler的dataTaskWithRequest:时这个闭包会在指定的delegateQueue上被调用。因为传了mainQueue所以成功/失败闭包直接运行在主线程所以可以安全地在闭包内部更新 UI如self.label.text ...不需要再手动dispatch_async(dispatch_get_main_queue())。3. 基于配置 自定义代理全功能模式这是最强大、最复杂的模式NSURLSession *session [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];适用场景大文件下载需要进度条、大文件上传、需要处理 HTTPS 证书校验didReceiveChallenge、需要拦截服务器重定向。特点可以实时接收到NSURLSessionDelegate、NSURLSessionDownloadDelegate等协议中的回调。内存管理会话对象会强引用retain代理对象self。如果self是 ViewController这就会造成循环引用导致页面dealloc不被调用造成内存泄漏。生成任务任务的类型任务类型创建方法前缀核心特征适用场景NSURLSessionDataTaskdataTaskWith...数据一次性加载到内存NSData中返回。调用 JSON 接口、获取图片二进制数据小图。NSURLSessionUploadTaskuploadTaskWith...专门负责把数据发送给服务器支持后台上传。提交头像、上传日志文件、表单提交。NSURLSessionDownloadTaskdownloadTaskWith...数据直接写入磁盘临时文件NSURL不占用 App 内存。支持断点续传。下载视频、更新包、大体积 ZIP 文件。NSURLSessionStreamTaskstreamTaskWith...建立 TCP/IP 流式连接读写数据按流处理。即时通讯IM、WebSocket 长连接。笔者目前还处于初始学习过程, 只接触到 NSURLSessionDataTask任务的回调方式闭包(Block) 和 代理 (delegate)回调方式方法特征优点缺点 / 限制Block 闭包Completion Handler方法名末尾带completionHandler:参数。代码紧凑发起和处理的逻辑写在一起易于阅读。无循环引用风险若会话无代理则无需关心内存泄漏。无法获取中间进度DownloadTask 除外它有单独的进度闭包。 无法处理服务器要求客户端证书Authentication Challenge。 无法拦截重定向。Delegate 代理响应协议方法创建会话时传入delegate:self并实现NSURLSessionDelegate等协议。精细控制可以实时监听didWriteData进度、didReceiveChallenge证书校验、willPerformHTTPRedirection重定向。分片接收数据在didReceiveData中手动拼接。代码分散逻辑割裂在多个回调方法中。极易造成循环引用必须手动调用invalidateAndCancel断开强引用。任务的创建方式输入方式方法名称特征能否设置 Method能否设置 Headers/Body适用场景传入NSURLdataTaskWithURL:downloadTaskWithURL:固定 GET不能简单的 GET 请求无需携带 Token 或特殊头部。传入NSURLRequestdataTaskWithRequest:uploadTaskWithRequest:自由设置POST/PUT/DELETE能通过setValue:forHTTPHeaderField:和HTTPBody需要登录态Authorization、需要传 JSON Body 的 POST 请求。// 创建请求地址NSString*strhttps://your-api.com/login?usernametestuserpassword123456;NSURL*url[NSURL URLWithString:str];// 创建请求类NSMutableURLRequest*request[NSMutableURLRequest requestWithURL:url];// HTTP 方法request.HTTPMethodGET;// 时间阈值request.timeoutInterval15;// 配置会话// 使用默认配置NSURLSessionConfiguration*config[NSURLSessionConfiguration defaultSessionConfiguration];// 创建会话NSURLSession*session[NSURLSession sessionWithConfiguration:config];// 通过 Request 创建NSURLSessionDataTask*task[session dataTaskWithRequest:request completionHandler:^(NSData*_Nullable data,NSURLResponse*_Nullable response,NSError*_Nullable error){if(error){NSLog(请求失败: %,error);}else{NSError*jsonErrornil;// 调用苹果原生 API 将服务器返回的二进制数据 (NSData) 转换为 Objective-C对象// 传入错误指针的地址, 如果二进制数据不是合法的 JSON 格式比如缺了一个引号或者是 HTML 报错页jsonError 就会被赋值为一个包含具体错误原因的对象而方法本身会返回 nil。id dict[NSJSONSerialization JSONObjectWithData:data options:0error:jsonError];if(jsonError){NSLog(JSON 解析失败);}else{NSLog(%,dict);}}}];//启动任务[dataTask resume];这是通过 requset 和 闭包 (Block) 回调的方式创建task, 还可以采用一个[session dataTaskWithURL:url completionHandler:]的方式去创建一个但是如果以后面的方式去创建的话就意味着是以一种GET方式去获取网络请求这样只能满足一些简单的网络请求而使用 request 方式来获取数据可以满足更复杂的情况。所以我们尽量采用request方法来获取网络请求采用request的方式可以满足更多需求下面是通过 URL 创建任务// 创建地址NSURL*url[NSURL URLWithString:https://api.example.com/public/data];// 配置会话// 使用默认配置NSURLSessionConfiguration*config[NSURLSessionConfiguration defaultSessionConfiguration];// 创建会话NSURLSession*session[NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]];// 创建任务直接传入 URLNSURLSessionDataTask*task[session dataTaskWithURL:url completionHandler:^(NSData*data,NSURLResponse*response,NSError*error){if(error){NSLog(请求失败: %,error);}else{NSError*jsonErrornil;// 调用苹果原生 API 将服务器返回的二进制数据 (NSData) 转换为 Objective-C对象// 传入错误指针的地址, 如果二进制数据不是合法的 JSON 格式比如缺了一个引号或者是 HTML 报错页jsonError 就会被赋值为一个包含具体错误原因的对象而方法本身会返回 nil。id dict[NSJSONSerialization JSONObjectWithData:data options:0error:jsonError];if(jsonError){NSLog(JSON 解析失败);}else{NSLog(%,dict);}}}];// 启动任务[task resume];通过URL创建任务就不用显式的去创建请求类启动任务启动任务的唯一正确方法:[task resume]刚刚创建好的任务, 处于 suspended (挂起) 的状态 , 它虽然存在, 但是不会发出任何网络请求

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价