读取超3万条JSON数据时Call Directory Extension因内存过高被杀死,求优化
解决Swift读取大JSON数组时的内存溢出问题
你的问题核心是一次性将整个大JSON文件加载到内存并解码,当元素超过3万时,内存占用会突破Extension的系统限制,导致进程被杀死。之前的分块处理没效果,大概率是分块逻辑仍未避免一次性加载全量数据。
下面是针对大JSON数组的优化方案,核心是流式解析,逐元素读取解码,彻底降低内存峰值:
优化后的代码
public func readReportFile() -> [ReportModel] { let fileURL = self.reportStoreUrl.appendingPathComponent(fileName).appendingPathExtension("json") guard let stream = InputStream(url: fileURL) else { print("Error: Could not open file stream at \(fileURL)") return [] } stream.open() defer { stream.close() } let jsonDecoder = JSONDecoder() var result: [ReportModel] = [] do { // 流式解析JSON,不一次性加载全量文件 let parserResult = try JSONSerialization.jsonObject(with: stream, options: []) guard let jsonArray = parserResult as? [[String: Any]] else { print("Error: JSON content is not an array") return [] } // 逐个解码元素,控制内存占用在单个模型级别 for jsonItem in jsonArray { guard let itemData = try? JSONSerialization.data(withJSONObject: jsonItem) else { print("Error: Failed to convert JSON item to data") continue } if let model = try? jsonDecoder.decode(ReportModel.self, from: itemData) { result.append(model) } } } catch { print("Error: Stream parsing failed: \(error)") return [] } return result }
针对5万+元素的进阶优化
如果未来数据量持续增长,即使返回全量[ReportModel]数组也会占用大量内存,建议根据业务场景调整:
- 边解析边持久化:解析一个元素就写入Core Data/Realm等本地存储,无需在内存中保留全量数组
- 异步流返回:将函数改为返回
AsyncThrowingStream<ReportModel, Error>,通过异步流逐个输出元素,完全规避全量内存占用
为什么之前的分块处理无效?
如果之前的分块是先读取整个文件到内存再拆分,本质还是一次性加载了所有数据,内存峰值没有降低。必须从文件读取阶段就采用流式处理,才是真正的内存优化。
内容的提问来源于stack exchange,提问作者a programer
相关产品推荐
相关产品推荐

