2014-10-22 64 views
0

我仍然在努力处理核心数据堆栈中传递对象的最佳方法。如何我开始供参考:绕过核心数据堆栈传递

  1. 应用是超级简单,单线程的核心数据访问是完美的,只有少数的意见和各需要一个MOC。以创建Core Data Stack和一个MOC的示例代码开始。 MOC存储在App Delegate中。

  2. 应用程序开始变得越来越复杂,并最终意识到为什么在App Delegate中存储MOC是一个糟糕的主意。重构的代码在App Delegate中创建MOC,并将MOC注入根视图控制器。从那里开始,App Delegate没有保留MOC,并且视图控制器将其注入到可能需要它的其他控制器中。

  3. 开始重构故事板中的应用程序视图。新的标签栏,一些导航控制器,分割视图控制器,你只知道一些不同的想法。步骤#2变成了一场噩梦。每当我对故事板中的应用程序视图层次进行更改时,我都需要重新调整每个视图控制器,以通过新层次结构传递MOC。当然,苹果说这是正确的方式,但我不确定我是否购买它,非常难以在不杀死代码的情况下进行简单的视图层级更改。现在我在我的应用程序的开头有4个视图,甚至不需要MOC。然而,这些视图是应用程序委托人与需要MOC的视图控制器的唯一链接。所以我被卡住注入MOC到所有这些视图控制器中,以便它们可以将它传递给另一个视图控制器,而无需每次使用MOC。

  4. 应用程序更加复杂,现在我想要一个线程化的核心数据堆栈。这意味着要传递持久性存储,以便某些“处理”对象可以在后台线程上创建自己的MOC。我应该创建一些可以帮助管理器的CoreDataStack对象吗? I.E.的对象,我可以要求主线程MOC,或要求一个新的'工人'背景MOC。看起来像现在第3步更加毫无意义,我的意思是我的应用程序中的每个视图都需要访问主线程MOC,而不是其他任何东西。我想我没有看到这一个改变了一段时间,但谁知道我已经改变了很多,因为我开始;)

我觉得“CoreDataStack”对象可以管理分布的想法MOC可能是一个好主意。这样,至少该对象可以抽象出我选择实现线程堆栈的方式的实现细节。 I.E.提供方法来掏出主要的MOC和背景MOC。

这似乎很好,直到我开始考虑如何传递这个堆栈对象。我可以做到苹果推荐的内容,并将其从控制器传递到控制器,将主线程MOC注入到每个视图控制器中。但正如我上面所说的,在故事板上重新工作大约5分钟,这使得这种情况迅速崩溃。更不用说将MOC传递给并不真正需要的视图,以便它们可以传递到层次结构中可能需要它的下一个视图。

最后我的问题。是否有更好的解决方案,而不是传递/注入MOC到每个视图控制器?

+0

使用核心数据和多线程环境中的对象可能会非常复杂。看看Magical Record,它会消除很多痛苦。 https://github.com/magicalpanda/MagicalRecord – sbarow 2014-10-22 05:00:28

+0

2是首选方式,特别是在使用嵌套上下文时。通过使用非正式协议,您可以使您的实施更轻松。如果遵循规则并为不同的工作机构创建新的上下文,并发不应该引入问题。 http://quellish.tumblr.com/post/97430076027/a-real-guide-to-core-data-concurrency – quellish 2014-10-23 02:12:58

回答

-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的访问次数,并避免了很多复杂性。

+0

我需要的不仅仅是id,即tableviews等整个上下文。 Ids和MOC仍然在不同的地方传递着同样的信息,它改变了故事情节,并重新进行了大规模的代码更新。 – lostintranslation 2014-10-22 14:35:16

+0

为了澄清,WWDC 2014会议@Vader提到了关于核心数据并发模型历史的讨论,而不是如何自行传递上下文的历史。 – quellish 2014-10-23 02:17:06

1

你说

应用开始变得更加复杂,终于实现了,为什么存储在App代表的MOC是一个坏主意。

你对这件事究竟有什么不满?对于你提到的应用程序委托或单例的问题是非常合适的解决方案。我只想从所有控制器删除应用程序委托代码

  • 不需要核心数据
  • 有一个对象作为伊娃(你可以从被管理对象的子类被管理对象上下文)

除非您有大量记录并需要提取结果控制器,否则您可以仅使用没有提取请求的对象图,因此核心数据层很好地“抽象出”。

相关问题