我仍然在努力解决核心数据堆栈中传递对象的最佳方法。我是如何开始参考的:
App非常简单,单线程核心数据访问非常完美,只有少数几个视图,每个都需要一个MOC。开始创建核心数据堆栈和一个MOC的示例代码。 MOC存储在App Delegate中。
应用程序开始变得更复杂,最终意识到为什么将MOC存储在App Delegate中是一个坏主意。重构代码以在App Delegate内创建MOC并将MOC注入根视图控制器。从那里App Delegate没有抓住MOC,并且视图控制器将其注入到可能需要它的其他控制器中。
开始在故事板中重构应用视图。新标签栏,一些导航控制器,拆分视图控制器,你只知道一些不同的想法。第二步变成了一场噩梦。每次我对故事板中的应用程序视图层次结构进行更改时,我都必须修改每个视图控制器以通过新的层次结构传递MOC。当然苹果说这是正确的方法,但我不确定我是否正在购买它,很难在不破坏代码的情况下进行简单的视图层次结构更改。此外,现在我的应用程序开始时有4个视图,甚至不需要MOC。但是,这些视图是从app委托到需要MOC的视图控制器的唯一链接。所以我很难将MOC注入到所有这些视图控制器中,这样他们就可以将它传递给另一个视图控制器而不必使用MOC。
应用程序更加复杂,现在我需要一个线程化的核心数据堆栈。这意味着遍历持久性存储,以便某些“处理”对象可以在后台线程上创建自己的MOC。我应该创建一些可以帮助管理器的CoreDataStack对象吗? I.E.我可以要求主线程MOC的对象,或者要求新的“工人”背景MOC。似乎现在步骤#3更加毫无意义,每一个我的意思是我的应用程序中的每个视图都需要访问主线程MOC而不是其他任何东西。我想我暂时没有看到这个改变,但是我知道自从我开始以来我已经改变了很多;)
我认为可以管理MOC分布的'CoreDataStack'对象的想法可能是一个好主意。这样至少该对象可以抽象出我选择实现线程堆栈的方式的实现细节。 I.E.提供排除主要MOC和背景MOC的方法。
在我开始思考如何传递这个堆栈对象之前,这看起来很棒。我可以完全按照苹果推荐的那样做,并将其从控制器传递给控制器,将主线程MOC注入每个视图控制器。但正如我上面所说的那样,在故事板上重新工作大约5分钟就会让这种情况迅速崩溃。更不用说将MOC传递给不真正需要它的视图,这样它们就可以传递到层次结构中可能需要它的下一个视图。
最后我的问题。对于我的用例是否有更好的解决方案,而不是传递/注入MOC到每个视图控制器???
答案 0 :(得分:1)
你说
应用程序开始变得更复杂,最终意识到为什么将MOC存储在App Delegate中是一个坏主意。
你究竟对此不喜欢什么?对于你提到的问题,app delegate或singleton是非常合适的解决方案。我只是从
的所有控制器中删除应用程序委托代码除非你有很多记录并且需要一个获取结果控制器,否则你可以使用没有获取请求的对象图,因此核心数据层很好地被抽象掉了#34;。
答案 1 :(得分:-2)
我使用的一种新技术是代理对象。基本上我所做的是创建一个模仿托管对象的struct
。对于所有读取操作,我使用此模拟对象。如果用户正在编辑数据但没有"已保存"它,我也使用模仿对象。只有当用户提交保存对象时才使用Core Data。那时我打电话给我在这里创建的MOC单身人士,
// My `AppDelegate` conforms to `UIApplicationDelegateWithPSC`
protocol UIApplicationDelegateWithPSC {
func providePersistentStoreCoordinator() -> NSPersistentStoreCoordinator
}
class ContextManager {
static let sharedInstance = ContextManager(concurrencyType: .mainQueueConcurrencyType)
private init(concurrencyType: NSManagedObjectContextConcurrencyType ) { }
lazy var context: NSManagedObjectContext = {
return {
let modelURL = Bundle.main.url(forResource: "Foo", withExtension: "momd")
let mom = NSManagedObjectModel(contentsOf: modelURL!)
let appDelegateWithPSC = UIApplication.shared.delegate as! UIApplicationDelegateWithPSC
let psc = appDelegateWithPSC.providePersistentStoreCoordinator()
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let storeURL = (urls[urls.endIndex-1]).appendingPathComponent("Bar")
var error: NSError? = nil
var store: NSPersistentStore?
do {
store = try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil)
} catch let error1 as NSError {
error = error1
store = nil
} catch {
fatalError()
}
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = psc
return managedObjectContext
}()
}()
}
我将上下文称为:
ContextManager.sharedInstance.context.performAndWait({
do {
let foo = NSEntityDescription.insertNewObject(forEntityName: "Foo", into: ContextManager.sharedInstance.context) as? Foo
// `mimicStruct` is the struct i've been using to avoid the headaches of complying with rules for manipulating ManagedObjects.
foo?.name = mimicStruct.name
try ContextManager.sharedInstance.context.save()
} catch {
}
})
通过在我的上下文中使用单例对象,我避免了多线程代码的复杂性。请注意,我也将它设为performAndWait
,这意味着我正在阻止,但由于我只在读取/写入数据库时才执行此操作,因此当微调器指示Loading...
时,用户通常需要暂停一下或Saving...
。我最终减少了MOC
的次数,避免了很多复杂性。