You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效存储大量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的批量插入能力,异步处理大量数据,避免主线程卡顿

实现示例

  1. 先在Core Data模型中创建UpNextItemEntity:

    • 属性:id(UUID,主键)、name(String)、artist(String)、fileExtension(String)
    • 可选:添加与AudioFile的to-one关联关系,减少冗余存储
  2. 批量插入代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 02:34:54