网络请求封装选Struct/Enum/Class?选型及包体积影响问题咨询
网络层类型选型问题解答
1. 此类场景优先使用Struct,Class可按需选择,Enum不适用
原因如下:
- 你的网络层实现属于无状态服务,当前
ModuleNetwork没有任何可变存储属性,所有逻辑都封装在方法内部,值类型的Struct完全能满足需求,不需要引用类型Class的引用计数额外开销 - Struct天然线程安全:值类型在传递时是独立拷贝,多线程请求场景下不会出现多端同时修改同一个实例的问题,不需要额外加锁保证线程安全,适配网络请求的高并发特性
- 你已经通过
ModuleNetworkProvider协议完成了能力抽象,不需要用到Class的继承特性来做代码复用,协议+扩展的组合反而能更灵活地抽离通用逻辑(比如统一解码、统一错误处理) - 仅当你需要给网络层增加可变全局状态时(比如全局请求重试计数、自定义请求队列存储),再切换为Class即可,因为有协议做抽象,类型切换对上层调用方完全无感知
- Enum完全不适用于该场景:Enum的设计目的是表达有限的同类型枚举值,哪怕用无case的Enum做命名空间,后续也无法扩展存储属性,灵活性远低于Struct
2. 使用Struct实现不会增大应用包体积
- 无存储属性的Struct初始化不需要分配额外内存,运行时开销和全局函数几乎一致
- Swift编译器对值类型有大量优化,这种无状态Struct的方法调用会在编译期做静态派发,比Class的动态派发性能更高,不会产生额外的运行时代码
- 即便你有数十上百个类似的功能模块Struct实现,只要通过统一协议做抽象,编译后不会产生冗余代码,反而比零散的全局函数实现包体积更小
可选优化建议
你可以把通用解码逻辑抽成协议扩展,减少每个Struct实现的重复代码:
extension ModuleNetworkProvider { func decode<T: Decodable>(from data: Data, as type: T.Type) throws -> T { return try JSONDecoder().decode(T.self, from: data) } }
调整后每个网络请求实现里的解码逻辑只需要调用该扩展方法即可,不需要重复写do-catch的解码模板代码。
内容的提问来源于stack exchange,提问作者Johhny Ios
相关产品推荐
相关产品推荐

