首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >推荐使用CoreData托管对象进行依赖注入吗?

推荐使用CoreData托管对象进行依赖注入吗?
EN

Stack Overflow用户
提问于 2017-04-03 14:56:35
回答 1查看 1.3K关注 0票数 2

考虑到我有一个由CoreData堆栈管理的类,我目前正在编写一个框架,我希望能够通过依赖项注入(理想情况下,只通过DI)创建对象。

我也在设计“快速失败”的心态(即尽快崩溃),并遵循坚实的原则。

该框架将与iOS 9-10兼容,可以用于ObjC和Swift (或混合目标),因此理想情况下,我不希望依赖于ObjC或Swift中的不交叉兼容特性。

这段代码应该在内部使用,而不是暴露给框架的使用者,正如约拿所指出的那样,公开这样的功能并不是一个非常可靠的选择。

问题:

我这里有两种不同的方法来创建我的对象,我不确定它们中的哪一种是正确的,是否有“首选”解决方案,还是使用中有较少错误的解决方案?

下面是一个代码片段来说明我的情况:

代码语言:javascript
复制
import CoreData
class Example: NSManagedObject {}

class DependencyClass: NSObject {}

extension Example
{
    public convenience init(with someDependency:DependencyClass,
                            context:NSManagedObjectContext)
    {
        let description = NSEntityDescription.entity(forEntityName: "Example", in: context)
        self.init(entity: description!, insertInto: context)
        //Configure the result object here
    }

    class func NotAConvenienceInit(with someDependency:DependencyClass,
                       context:NSManagedObjectContext) -> Example
    {
        let selfClassName = String(describing: self)
        let result = NSEntityDescription.insertNewObject(forEntityName: selfClassName, into: context) as! Example
        //Configure the result object here
        return result
    }
}

let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
let dependency = DependencyClass()

//Usecase A
let myExample = Example(with: dependency, context: context)

//Usecase B
let anotherExample = Example.NotAConvenienceInit(with: dependency, context: context)

为了方便起见,我一直在考虑可失败的初始化器,我很想知道,一旦init方法结束,我的对象就会有效。我认为这两种方式都可以通过各种机制保证这一点。

苹果似乎更喜欢+insertNewObjectForEntityForName:inManagedObjectContext:他们的文件,这就是为什么我想出了这两种方法。

PS :我还在学习Swift,如果这似乎是一个已经解决的问题,我会提前道歉。在看了很多网站上的文章后,我没有找到一个决定性的解决办法,因此我转向这样做。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-03 15:54:42

我试图做同样的事情,我的结论是,最好避免这种方法,而是保持行为,特别是需要其他依赖于模型的行为。

为什么?

  1. Swift和Objective实际上没有为您提供任何工具来禁止使用现有的构造函数,因此,虽然您可以使用DI参数提供替代方法,但是您几乎无法确保NSManagedObjectNSEntityDescription不用于创建模型的实例。
  2. 此外,NSManagedObject.init(entity:insertInto:)NSEntityDescription.insert​New​Object(for​Entity​Name:​into:​)用于插入新的模型实例,但并不是创建模型类实例的唯一方法。看看NSManagedObjectawake​From​Fetch()awake(from​Snapshot​Events:​) (和awake​From​Insert())。 假设我创建了一个NSFetchedResultsController,其中包含一个fetch请求,返回一个框架模型。如果我调用controller.fetchedObjects,我将得到您的模型的实例。类似地,我可以直接执行NSFetchRequest。您可以使用单例容器在awake...实现中提供依赖项,但这限制了创建代码指定这些依赖项的能力,并导致另一个问题:
  3. 托管对象上下文队列。由于NSManagedObjects与内容相关联,并且必须在该上下文的队列上使用,因此您需要小心依赖项,引入对错误队列上模型的访问,并且经常希望依赖项的作用域限定为特定上下文。

相反,我会考虑:

  • 让您的框架返回非NSManagedObject模型,这些模型(可能是不变的)状态快照来自您的核心数据存储区。如果您可以避免向您的框架的使用者公开使用Core数据,那么您可以为他们提供不受特定并发队列约束的模型,并且您可以完全拥有这些模型的生命周期。
  • 避免模型中的任何外部依赖,并将此类行为转移到服务类或其他接口中,这样可以更容易地使用DI。确保这些服务类尊重给出的任何模型的并发队列,这样您的所有接口都可能需要异步。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43187929

复制
相关文章

相似问题

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