SwiftData @Model对象无法跨应用启动持久化(仅内存生效)问题求助
首先,看到你说增删操作在运行时正常,但重启后数据全没了,大概率是数据保存时出错但被你忽略了,或者模型里有SwiftData无法正确持久化的属性,我帮你梳理几个核心问题和对应的解决办法:
1. 先把保存时的错误暴露出来
你在addVod里用了try? context.save(),这种写法会直接吞掉所有保存时的异常——哪怕SwiftData因为属性无法编码、类型不匹配等原因保存失败,你也完全看不到任何提示。
先把这段代码改成带错误捕获的版本,这是定位问题的关键:
func addVod(chosenQuality: M3U8Parser.MasterPlaylist, vodmetada: VodsMetaData) { let vodModel = VodModel(chosenQuality: chosenQuality, vodmetada: vodmetada) allActiveVods.append(vodModel) context.insert(vodModel) do { try context.save() print("Vod 保存成功!") } catch { print("Vod 保存失败:\(error.localizedDescription)") print("详细错误信息:\(error)") // 这里可以根据错误类型做针对性处理,比如回滚上下文 } }
运行后如果保存失败,控制台会输出具体错误原因,能帮你直接定位到问题点。
2. 给自定义Codable类型明确持久化规则
你的VodModel里有两个复杂的自定义类型:chosenQuality(M3U8Parser.MasterPlaylist结构体)和state(带关联值的vodState枚举)。SwiftData对这类非基础类型的默认处理可能不稳定,建议给它们加上@Attribute(.externalStorage)注解,告诉SwiftData把它们序列化成JSON后再存储:
@Attribute(.externalStorage) var chosenQuality: M3U8Parser.MasterPlaylist @Attribute(.externalStorage) var state: vodState
另外要重点检查带关联值的vodState枚举:如果是自动合成Codable,要确保所有关联值的类型都支持Codable;如果是手动实现encode(to:)和init(from:),要确认关联值的编码/解码逻辑没有遗漏,这是很容易踩的坑。
3. 修复明显的类型不匹配问题
我注意到VodModel的thumbnail是Data?类型,但初始化时你赋值的是vodmetada.thumbnailURL(从变量名看应该是URL类型)——这明显类型不匹配啊!虽然你说模型编译没问题,大概率是你写代码时的笔误(比如实际应该是vodmetada.thumbnailData,或者VodsMetaData里的thumbnailURL被你定义成了Data)。这个问题必须修复,否则要么编译报错,要么存入错误数据导致后续异常。
4. 其他需要确认的细节
savedLocationURL是URL?类型,SwiftData默认支持URL的持久化,这点没问题,但如果是临时目录的URL,重启后会失效,但不会影响数据本身的保存。@Transient private var downloadTask: Task<Void, Never>?的写法正确,这个临时任务属性不会被持久化,符合你的需求。- 确保
VodModel的id是唯一的——你用vodmetada.vodID + chosenQuality.res生成id,只要chosenQuality.res能区分不同画质,这个唯一标识就没问题。
先按照上面的步骤排查,尤其是第一步把错误打印出来,基本就能找到数据无法持久化的根源了!
内容来源于stack exchange

