如何高效存储大量UpNextItem数组?Core Data相关存储方案咨询
优化大量UpNextItem数组的存储方案
针对10000+量级的UpNextItem数组存储卡顿问题,以下是几种高效的优化方案:
1. 改用二进制格式编码(PropertyListEncoder)
JSONEncoder基于文本序列化,处理大量数据时效率偏低,而PropertyListEncoder的二进制格式编码/解码速度远快于JSON,且同样支持结构体序列化。
优化后的代码
func saveUpNextItems() { // 放到后台队列执行,避免阻塞主线程 DispatchQueue.global(qos: .background).async { [weak self] in guard let items = self?.upNextManager.upNextItems else { return } let encoder = PropertyListEncoder() encoder.outputFormat = .binary // 二进制格式比XML更高效 do { let data = try encoder.encode(items) let fileURL = FileManager.upNextQueueURL.appendingPathComponent("upNextItems.plist") try data.write(to: fileURL) } catch { print(error) } } }
2. 利用Core Data存储UpNext队列
由于UpNextItem与AudioFile结构高度一致,且需要支持同一音频的多实例,直接用Core Data存储是更长期的解决方案:
- 新建
UpNextItemEntity实体,添加UUID类型的id属性,以及与AudioFile的关联关系(或冗余存储name、fileExtension作为标识) - 利用Core Data的批量插入能力,异步处理大量数据,避免主线程卡顿
实现示例
先在Core Data模型中创建
UpNextItemEntity:- 属性:
id(UUID,主键)、name(String)、artist(String)、fileExtension(String) - 可选:添加与
AudioFile的to-one关联关系,减少冗余存储
- 属性:
批量插入代码:
func saveUpNextItemsToCoreData() { DispatchQueue.global(qos: .background).async { [weak self] in guard let self = self, let items = self.upNextManager.upNextItems else { return } let context = self.persistentContainer.newBackgroundContext() context.performAndWait { let batchInsert = NSBatchInsertRequest(entity: UpNextItemEntity.entity(), objects: items.map { item in [ "id": item.id, "name": item.name, "artist": item.artist, "fileExtension": item.fileExtension // 若关联AudioFile,需先查询对应的实体: // "audioFile": self.fetchAudioFile(withName: item.name, extension: item.fileExtension, in: context) ] }) batchInsert.resultType = .count do { let result = try context.execute(batchInsert) as? NSBatchInsertResult print("插入成功 \(result?.result ?? 0) 条数据") try context.save() } catch { print(error) } } } }
3. 强制异步执行原逻辑
如果暂时不想换存储方案,至少要把编码和写入操作放到后台队列,避免阻塞主线程导致UI卡顿:
func saveUpNextItems() { DispatchQueue.global(qos: .background).async { [weak self] in guard let items = self?.upNextManager.upNextItems else { return } do { let data = try JSONEncoder().encode(items) try data.write(to: FileManager.upNextQueueURL.appendingPathComponent("upNextItems")) } catch { print(error) } } }
4. 分块存储(超大量级可选)
如果数据量突破十万级,可以将数组拆分成多个小块,每块单独存储为一个文件,读取时再合并。10000级数据通常无需此操作,但可作为极端场景的备选方案。
内容的提问来源于stack exchange,提问作者User95797654974
相关产品推荐
相关产品推荐

