在上下文之外创建NSManagedObject

4

我阅读了很多关于这个问题的主题,但并没有找到一个恰当的答案。我想创建一个NSManagedObject实例,却不需要上下文。

原因是:应用从服务器接收到SOAP响应。这个响应必须被保存到Core Data中。这个响应看起来像一棵树。

我的想法是重写每个实体的init方法,以便它可以接收数据。然后,我将能够创建根实体,而创建根实体将调用另一个实体的创建,以此类推。

负责发出请求的应用部分是通过泛型实现的。有一个协议,说明每个响应类都必须拥有init方法,例如:

public protocol Parsable {
    init(data: Data)
}  

正如您所看到的,这里没有上下文的空间。相反,我想一次性创建所有这些实体并将其保存到上下文中。

另一个解决方案是制作重复的类,用响应填充它,然后将其复制到我的Core Data实体中。但这是不必要的重复,我想避免。

任何想法都将不胜感激。


基本上,在Core Data中,您不能创建没有上下文的NSManagedObject实例。但是这有什么好处呢?无论如何,您都必须将实例插入上下文中,并且在创建和插入所有实例之后应该调用save命令一次 - vadian
可能是 https://dev59.com/vMjts4cB2Jgan1znAONP 的重复问题。 - Martin R
@vadian,感谢您的回答。确实只会调用一次保存。正如我上面提到的,我在处理响应的地方没有访问moc的权限。 - Yura
然后我会使用自定义结构作为临时存储。 - vadian
@vadian,谢谢,我现在用这个解决方案。 - Yura
2个回答

1
实际上,“在这里采用复制类的替代方案”是唯一的好解决方案,原因有很多。
在你的情况中,你已经有了两个表示相同实体的对象。我假设你从服务器收到的是一个JSON解析成字典的对象,它也代表着同一个实体。所以,为了将其转换为核心数据,你已经有了一个从字典到核心数据管理对象的映射器。
假设直接使用托管对象在应用程序的高层级中是好的,这是错误的。我们使用包装器来处理这个问题。所以你需要一个类来处理所有的数据传输,同时拥有使用任何模块和任何线程中的数据的所有接口。这就是为什么你需要将所有数据传输到一个新类中,该类可以包装托管对象。
所以考虑你有一个名为MyObject的类,一个核心数据类MyObjectEntity,可能还有一个API的字典。那么MyObject的接口将是:
init(entity: MyObjectEntity) // Wraps the entity and copies all fields to this class
init(descriptor: [String: Any]) // Copies all fields to this class
var descriptor: [String: Any] // Returns a dictionary ready to be parsed to JSON
func writeToManagedObject() // Will copy all the data to managed object. If the object exists it will modify it, if not it will create a new one. This will not save the database.

通过一些子类化和扩展,即使您有许多需要映射的模型,也可以创建一个非常好的系统。由于该类对于从任何线程访问和/或保存上下文都是完全不敏感的,因此它已经准备好进行任何其他高级操作。就我所知,您甚至可以将其用作MVVM。


1
谢谢你的回答。你能否解释一下在应用程序的更高层中直接使用托管对象有什么问题吗?谢谢。 - Yura
1
多线程是一个问题;如果你需要临时/可丢弃的对象,你需要多个上下文,这通常会导致冲突;它们在出现故障时是不可预测的;一个单一的对象可以被多个模块同时修改而你却不知道;当你需要进行类型转换时,比如将NSDate转换为Date或UIImage转换为NSData时,就会出现重复的属性,使用可变转换时要注意;...但是,如果你的应用程序很简单,并且如果它对你有用,那么就不要费心处理这些事情,就像你平常使用它们一样。 - Matic Oblak

0

创建一个数据类,当需要时发出NSManagedObject子类,并将其移交给具有moc的代码部分。对于程序的其余部分,只需处理非MOC类。以下是示例。

示例:

class MyMOCDataClass : NSManagedObject {
public var myName:String
public var myAge:Int16
}

class MyDataClass {
public var myName:String
public var myAge:Int16

init(...){ 
//whatever else you may or may not need to do here. 
}

func emitWithMoc( moc: NSManagedObjectContext ) -> MyMOCDataClass {
var tmpMocClass = MyMOCDataClass( context: moc )
tmpMocClass.myName = self.myName
tmpMocClass.myAge = self.myAge
return tmpMocClass;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接