我正在嘗試為 iOS 構建一個 Swift 應用程式。我有一個簡單的資料模型、一個物體 GameModule 和另一個具有一對多關系的物體 GameModuleFile(一個 GameModule 對多個 GameModuleFile)。
我從磁盤加載一個 zip 檔案,解壓縮并將檔案填充到與最后一個模塊相關的 GameModuleFile 物體中。
如果我同步運行它,它會完美運行。但是如果我異步運行它,檔案不會與關系一起存盤到核心資料中。代碼仍然運行,沒有錯誤,但關系不存在。
實際上,更有趣的是,對于小 zip 檔案(數百個檔案)來說,這種關系是可以的,但對于大檔案(數千個檔案)來說,這種關系就不存在了。
有什么幫助嗎?
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 建議和一些谷歌搜索,我使用后臺背景關系修改了代碼以將檔案加載到核心資料中。現在正在作業。
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
}
}
}
}
}
uj5u.com熱心網友回復:
問題可能是由于您的 loadFiles 函式在后臺佇列上運行,并且 managedObjectContext 已初始化為與主佇列一起使用。
您只能訪問與背景關系關聯的調度佇列上的托管物件。
嘗試將此啟動引數添加到您的方案中:
-com.apple.CoreData.ConcurrencyDebug 1
使用此引數,如果您錯誤地訪問了錯誤佇列上的托管物件,應用程式將引發例外。
如果是這種情況,您需要創建與后臺執行緒關聯的第二個 managedObjectContext 以進行后臺處理。
您可以在此鏈接中找到更多詳細資訊: https ://developer.apple.com/documentation/coredata/using_core_data_in_the_background
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508481.html