首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步存储核心数据破坏关系

异步存储核心数据破坏关系
EN

Stack Overflow用户
提问于 2022-09-11 16:43:04
回答 1查看 51关注 0票数 1

我正试图为iOS构建一个Swift应用程序。我有一个简单的数据模型,一个实体GameModule和另一个实体GameModuleFile,其关系是一对多(一个GameModule到多个GameModuleFile)。

我从磁盘加载一个zip文件,解压缩它,并将文件填充到与最后一个模块相关的GameModuleFile实体中。

如果我运行同步,它的工作就完美了。但是,如果我运行它的异步,文件不会存储到核心数据与关系。代码仍然在运行,不会出现错误,但是这种关系并不存在。

实际上,更有趣的是,这种关系可以用于小型压缩文件(数百个文件),但对于大型文件(数千个文件)则没有关系。

有什么帮助吗?

代码语言:javascript
复制
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数据中。现在起作用了。

代码语言:javascript
复制
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
                }
            }
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73680964

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档