鉴于我有一个由CoreData堆栈管理的类, 我目前正在编写一个Framework,我希望能够通过依赖注入创建我的对象(理想情况下,只能通过DI)。
我也在设计"快速失败"心态(即尽快崩溃),并遵循SOLID原则。
该框架将与iOS 9-10兼容,并且可以在ObjC和Swift(或混合目标)中使用,因此我理想地不希望依赖于ObjC或Swift中的非交叉兼容功能。
这段代码意在内部使用,而不是暴露给框架的消费者,因为Jonah指出暴露这些功能并不是一个非常可靠的选择。
我有2种不同的方法来创建我的对象,我不确定是否 如果有一个"首选"它们中的任何一个都是纠正的。解决方案,或使用较少陷阱的解决方案?
这是一个代码片段来说明我的情况:
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提供可用的初始化程序,我很好地认为,一旦init方法结束,我就会保证"我的对象是有效的。我认为两种方式都可以通过各种机制来保证。
Apple似乎更喜欢their documentation中的+insertNewObjectForEntityForName:inManagedObjectContext:
,这就是我提出这两种方法的原因。
答案 0 :(得分:2)
我试图做同样的事情,我的结论是,最好避免这种方法,而是保持行为,特别是需要其他依赖关系的行为。
为什么?
Swift和Objective-C真的没有给你任何工具来禁止使用现有的构造函数,所以当你可以提供DI参数的替代方案时,你几乎无法确保NSManagedObject
或NSEntityDescription
不用于创建模型的实例。
此外,NSManagedObject.init(entity:insertInto:)
和NSEntityDescription.insertNewObject(forEntityName:into:)
用于插入新模型实例,但不是创建模型类实例的唯一方法。请查看NSManagedObject
的{{1}}和awakeFromFetch()
(以及awake(fromSnapshotEvents:)
)。
假设我创建了一个带有获取请求的awakeFromInsert()
,返回一个框架模型。如果我打电话给NSFetchedResultsController
,我会得到你模特的实例。同样,我可以直接执行controller.fetchedObjects
。您可以使用单例容器在NSFetchRequest
实现中提供依赖项,但这会限制创建代码指定这些依赖项的能力并导致另一个问题:
托管对象上下文队列。由于awake...
与内容绑定并且必须在该上下文的队列中使用,因此您需要注意在错误队列上引入对模型的访问的依赖关系,并且通常希望将依赖关系作用于特定上下文。
相反,我会考虑: