我正试图为iOS构建一个Swift应用程序。我有一个简单的数据模型,一个实体GameModule和另一个实体GameModuleFile,其关系是一对多(一个GameModule到多个GameModuleFile)。
我从磁盘加载一个zip文件,解压缩它,并将文件填充到与最后一个模块相关的GameModuleFile实体中。
如果我运行同步,它的工作就完美了。但是,如果我运行它的异步,文件不会存储到核心数据与关系。代码仍然在运行,不会出现错误,但是这种关系并不存在。
实际上,更有趣的是,这种关系可以用于小型压缩文件(数百个文件),但对于大型文件(数千个文件)则没有关系。
有什么帮助吗?
import SwiftUI
import UniformTypeIdentifiers
struct GameModuleListView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [SortDescriptor(\.order)]) var gameModules: FetchedResults<GameModule>
@State private var loadModuleTrigger = false
var body: some View {
NavigationView {
List {
ForEach(gameModules, content: GameModuleRow.init)
}
}
.navigationViewStyle(StackNavigationViewStyle())
.fileImporter(isPresented: $loadModuleTrigger, allowedContentTypes: [.zip], allowsMultipleSelection: false, onCompletion: loadModule)
}
func loadModule(res: Result<[URL], Error>) {
let url = try! res.get()[0]
DispatchQueue.global(qos: .userInitiated).async {
try? gameModules[gameModules.count - 1].loadFiles(context: moc, url: url)
}
}
}
import ZIPFoundation
extension GameModule {
func loadFiles(context moc: NSManagedObjectContext, url: URL) throws {
let archive = try GameModule.getArchiveFromUrl(url: url)
for entry in archive {
if entry.path.last! != "/" {
_ = try? archive.extract(entry) { data in
let file = GameModuleFile(context: moc)
file.filePath = entry.path
file.blob = data
file.ownerModule = self
}
}
}
try? moc.save()
}
}更新
基于下面的@cgontijo建议和一些googling,我使用背景上下文修改了代码,将文件加载到Core数据中。现在起作用了。
import SwiftUI
import UniformTypeIdentifiers
struct GameModuleListView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: [SortDescriptor(\.order)]) var gameModules: FetchedResults<GameModule>
@State private var loadModuleTrigger = false
var body: some View {
NavigationView {
List {
ForEach(gameModules, content: GameModuleRow.init)
}
}
.navigationViewStyle(StackNavigationViewStyle())
.fileImporter(isPresented: $loadModuleTrigger, allowedContentTypes: [.zip], allowsMultipleSelection: false, onCompletion: loadModule)
}
func loadModule(res: Result<[URL], Error>) {
moc.perform {
let newModule = try! GameModule(moc)
let url = try! res.get()[0]
try? newModule.loadFiles(context: moc, url: url)
try? moc.save()
}
}
}
import ZIPFoundation
extension GameModule {
func loadFiles(context moc: NSManagedObjectContext, url: URL) throws {
let archive = try GameModule.getArchiveFromUrl(url: url)
for entry in archive {
if entry.path.last! != "/" {
_ = try? archive.extract(entry) { data in
let file = GameModuleFile(context: moc)
file.filePath = entry.path
file.blob = data
file.ownerModule = self
}
}
}
}
}发布于 2022-09-11 20:11:48
这个问题可能是由于您的loadFiles函数在后台队列上运行,并且managedObjectContext被初始化以与主队列一起使用。
您只能访问与上下文关联的调度队列上的托管对象。
尝试将此启动参数添加到您的计划中:
-com.apple.CoreData.ConcurrencyDebug 1
使用此参数,如果错误地访问错误队列上的托管对象,应用程序将引发异常。
如果是这种情况,则需要创建与后台线程关联的第二个managedObjectContext,以便进行后台处理。
您可以在以下链接中找到更多详细信息:https://developer.apple.com/documentation/coredata/using_core_data_in_the_background
https://stackoverflow.com/questions/73680964
复制相似问题