{"id":13696029,"url":"https://github.com/indulgeIn/YBNetwork","last_synced_at":"2025-05-03T14:30:46.727Z","repository":{"id":56928853,"uuid":"180271750","full_name":"indulgeIn/YBNetwork","owner":"indulgeIn","description":"基于 AFNetworking 网络中间层，功能细致易拓展","archived":false,"fork":false,"pushed_at":"2019-12-29T03:59:17.000Z","size":253,"stargazers_count":148,"open_issues_count":2,"forks_count":21,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-12T15:59:54.611Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/indulgeIn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-09T02:47:14.000Z","updated_at":"2025-02-14T08:17:40.000Z","dependencies_parsed_at":"2022-08-21T05:50:59.074Z","dependency_job_id":null,"html_url":"https://github.com/indulgeIn/YBNetwork","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indulgeIn%2FYBNetwork","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indulgeIn%2FYBNetwork/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indulgeIn%2FYBNetwork/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/indulgeIn%2FYBNetwork/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/indulgeIn","download_url":"https://codeload.github.com/indulgeIn/YBNetwork/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252203144,"owners_count":21710897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T18:00:35.690Z","updated_at":"2025-05-03T14:30:46.037Z","avatar_url":"https://github.com/indulgeIn.png","language":"Objective-C","funding_links":[],"categories":["Networking"],"sub_categories":[],"readme":"# YBNetwork\n\n[![Cocoapods](https://img.shields.io/cocoapods/v/YBNetwork.svg)](https://cocoapods.org/pods/YBNetwork)\u0026nbsp;\n[![Cocoapods](https://img.shields.io/cocoapods/p/YBNetwork.svg)](https://github.com/indulgeIn/YBNetwork)\u0026nbsp;\n[![License](https://img.shields.io/github/license/indulgeIn/YBNetwork.svg)](https://github.com/indulgeIn/YBNetwork)\u0026nbsp;\n\n基于 AFNetworking 二次封装，功能细致易拓展。\n\n设计原理博客：[谈谈 iOS 网络层设计](https://www.jianshu.com/p/fe0dd50d0af1)\n\n参考思路：[iOS应用架构谈 网络层设计方案](https://casatwy.com/iosying-yong-jia-gou-tan-wang-luo-ceng-she-ji-fang-an.html)\n\u003cbr\u003e参考源码：[YTKNetwork](https://github.com/yuantiku/YTKNetwork) [CTNetworking](https://github.com/casatwy/CTNetworking)\n\n\n## 特性\n\n- 支持缓存写入模式、读取模式、有效时长等自定义配置 (同时享有来着 YYCache 的优越性能)\n- 支持网络落地重定向\n- 支持发起请求和响应回调的预处理\n- 支持网络落地异步重定向\n- 重复请求处理策略选择\n- 网络请求释放策略选择\n- 支持 Block 和 Delegate 回调方式\n- 代码层级简单，便于功能拓展\n\n\n## 安装\n\n### CocoaPods\n\n1. 在 Podfile 中添加 `pod 'YBNetwork'`。\n2. 执行 `pod install` 或 `pod update`。\n\n若搜索不到库，可使用 rm ~/Library/Caches/CocoaPods/search_index.json 移除本地索引然后再执行安装，或者更新一下 CocoaPods 版本。\n\n### 手动导入\n\n1. 下载 YBNetwork 文件夹所有内容并且拖入你的工程中。\n2. 链接以下 frameworks：\n* AFNetworking \n* YYCache\n\n\n## 用法\n\n可下载 DEMO 查看示例。\n\n### 基本使用\n\n#### 1、第一步\n\n创建子类继承自`YBBaseRequest`，并且在构造方法中初始化一些通用的配置 (比如服务器地址、解析器)\n```\n@interface DefaultServerRequest : YBBaseRequest\n@end\n\n@implementation DefaultServerRequest\n- (instancetype)init {\n    self = [super init];\n    if (self) {\n        self.baseURI = @\"https://www.baidu.com\";\n    }\n    return self;\n}\n- (AFHTTPRequestSerializer *)requestSerializer {...}\n- (AFHTTPResponseSerializer *)responseSerializer {...}\n@end\n```\n如果项目接口来自不同的接口团队（往往通用配置不同），那么就为每一个接口团队子类化一个`YBBaseRequest`，然后分别配置通用配置。\n\n#### 2、第二步\n\n创建具体接口配置，有两种方式，一种是直接实例化`DefaultServerRequest`，一种是继续子类化`DefaultServerRequest`:\n```\n//直接实例化\nDefaultServerRequest *request = [DefaultServerRequest new];\nrequest.requestMethod = YBRequestMethodGET;\nrequest.requestURI = @\"...\";\nrequest.requestParameter = @{...};\n```\n```\n//继续子类化\n@interface SearchWeatherRequest : DefaultServerRequest\n@end\n@implementation SearchWeatherRequest\n- (YBRequestMethod)requestMethod {\n    return YBRequestMethodGET;\n}\n- (NSString *)requestURI {\n    return @\"...\";\n}\n- (NSDictionary *)requestParameter {\n    return @{...};\n}\n@end\n```\n\n#### 3、第三步\n\n发起网络请求，设置回调：\n```\n//Block\n__weak typeof(self) weakSelf = self;\n[request startWithSuccess:^(YBNetworkResponse * _Nonnull response) {\n    __strong typeof(weakSelf) self = weakSelf;\n    if (!self) return;\n} failure:^(YBNetworkResponse * _Nonnull response) {\n    __strong typeof(weakSelf) self = weakSelf;\n    if (!self) return;\n}];\n\n//Delegate\nrequest.delegate = self; //代理方法回调结果\n[request start];\n```\n目前的内部实现是，若有重复的网络请求发起，将只回调最新的 Block，而 Delegate 方式会每次都回调。\n\n注意：虽然 Block 方式就算不弱引用`self`也不会循环引用 (内部会回调完成后破除循环)，但是为了避免延长`self`的生命周期，强烈建议使用弱引用，不然可能会导致网络请求释放策略失效。如果你是主导者，那么可以规定必须使用 Delegate 方式回调，从源头上避免延长网络响应接受者生命周期。\n\n\n\n### 请求和响应预处理\n\n往往我们需要为所有请求参数添加一些字段，比如设备ID，用户ID。\n只需要在一级子类`DefaultServerRequest`中重载父类方法就行了：\n```\n@implementation DefaultServerRequest\n...\n//请求预处理\n- (NSDictionary *)yb_preprocessParameter:(NSDictionary *)parameter {\n    //预处理所有请求参数\n}\n- (NSString *)yb_preprocessURLString:(NSString *)URLString {\n    //预处理所有请求URL字符串\n}\n//请求响应预处理\n- (void)yb_preprocessSuccessInChildThreadWithResponse:(YBNetworkResponse *)response {\n    //预处理请求成功\n}\n- (void)yb_preprocessSuccessInMainThreadWithResponse:(YBNetworkResponse *)response {\n    //预处理请求成功\n}\n...\n@end\n```\n\n\n### 重定向\n\n网络落地重定向使用此方法：\n```\n- (void)yb_redirection:(void (^)(YBRequestRedirection))redirection response:(YBNetworkResponse *)response {\n    // 同步或异步的做一些事情\n    redirection(YBRequestRedirectionSuccess);\n}\n```\n使用`redirection`闭包来达到可异步重定向的能力，在这之间可以做一些具体网络接口无感知的逻辑。\n\n\n### 为响应对象添加属性\n\n`YBNetworkResponse` 包含必要的响应数据，可以添加额外属性，在网络响应预处理时为这些属性赋值，那么具体接口调用方就可以很方便的拿到这些处理后的值了。建议创建一个`YBNetworkResponse`的分类，使用 Runtime 的关联属性来拓展。\n\n\n### 缓存处理\n\n缓存处理配置都在`request.cacheHandler`变量`YBNetworkCache`类中，支持以下配置：\n- 内存/磁盘存储方式\n- 缓存命中后是否继续发起网络请求\n- 缓存的有效时长\n- 定制缓存的 key\n- 直接配置 YYCache\n\n#### 缓存有效性验证\n\n内部会在业务处理完成网络响应数据后尝试进行缓存，且提供一个`shouldCacheBlock`可根据请求响应成功数据判断是否需要缓存（比如仅当 `code == 0` 时数据有效允许缓存）。\n\n\n### 重复网络请求处理策略\n\n`request.repeatStrategy`变量配置，三种策略：\n1. 允许重复网络请求\n2. 取消最旧的网络请求\n3. 取消最新的网络请求\n\n举几个例子，当接口数据并不会在短时间变化时，重复发起网络请求就会浪费网络资源，可以选择方案 2 或 3；比如在搜索业务中，用户往往频繁的调用搜索接口，而发起一次搜索时，之前的搜索请求一般是没有意义了，就可以选用方案 2。\n\n\n### 网络请求释放策略\n`request.releaseStrategy`变量配置，有几种方式可以选择：\n1. 网络任务会持有 YBBaseRequest 实例，网络任务完成 YBBaseRequest 实例才会释放\n2. 网络请求将随着 YBBaseRequest 实例的释放而取消\n3. 网络请求和 YBBaseRequest 实例无关联\n\n举几个例子，若你的控制器出栈以后希望取消未落地的网络请求，那么就使用方案 2，注意管理好 YBBaseRequest 的生命周期就行了；若你的网络请求是不论如何都不希望它取消的，那么使用方案 3；若你希望网络请求任务始终持有 YBBaseRequest 实例避免它提前释放，那么使用方案 1。\n\n\n## 业务使用 Tips\n\n#### 1、使用 block 回调注意事项\n- 外部变量和 block 相互强持有也没关系，在网络回调完成过后组件会断开循环引用。\n- 尽量保证闭包内部捕获的变量是弱引用，避免延长被捕获变量的生命周期。\n\n#### 2、使用 delegate 回调注意事项\n当多个 request 的代理都是同一个对象时，需要通过返回的 request 判断具体网络请求；所以若使用代理回调建议外部应该持有这个 request 便于比较。\n\n#### 3、重复请求\n只需要持有 request，当对同一个 reqeust 多次进行 start 发起网络请求时，组件提供的几种重复请求策略便可以工作了。\n\n#### 4、网络安全落地\n若使用 block 方式回调并且 block 强持有了外部变量，那么在网络结束之前外部变量不会释放。弱外部变量在业务中已经不存在了（比如出栈了），那么此时回调会出现隐患（最常见的就是野指针）。\n\n- 使用 block 回调时，最好做一下业务落脚点所有变量是否可用的判断（回调提取一个方法能减少判断，这时不如用 delegate 回调）。\n- 使用 delegate 回调只需要保证代理者的可用性，所以比较安全。\n- 在 request 未持有外部变量时，在外部变量 `dealloc` 时调用 request 的 `cancel` 方法可以取消网络请求，这样就不会有回调了，保证安全。\n- 更便捷的方法是使用“网络请求将随着 request 实例的释放而取消”的策略（`request.releaseStrategy`），然后 reqeust 释放时网络请求将自动取消。\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FindulgeIn%2FYBNetwork","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FindulgeIn%2FYBNetwork","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FindulgeIn%2FYBNetwork/lists"}