有没有一种方法来实例化NSManagedObject而不插入它?

问题描述:

我有一个用户界面来插入交易。一旦用户点击一个加号,他就得到了屏幕,我想实例化我的核心数据NSManagedObject实体,让用户在其上工作。然后当用户点击保存按钮时,我将调用保存功能。有没有一种方法来实例化NSManagedObject而不插入它?

这样下来操作的代码:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; 
//even if i dont call save: its going to show up on my table 
[self.managedObjectContext save:&error] 

P.S我在该表使用NSFetchedResultsController和我看到NSFetchedResultsController被插入部和对象表中。

我的想法是,如果有一种方法来实例化事务NSManagedObject我可以更新它与保存直到客户端选择。

使用零MOC存在一个基本问题:不同MOC中的对象不应该彼此引用—这大概也适用于关系的一方具有零MOC时。如果你保存会发生什么? (当你的应用程序的另一部分保存时会发生什么?)

如果你的对象没有关系,那么你可以做很多事情(比如NSCoding)。

您可能能够在NSPredicate中使用-[NSManagedObject isInserted](推测在插入和成功保存之间为YES)。或者,您可以使用具有相同行为的瞬态属性(在awakeFromInsert中将其设置为YES,在willSave中将其设置为NO)。如果您的应用程序的不同部分保存,这两种方式都可能会产生问题。

使用第二MOC是如何CoreData是“应该”被使用,虽然;它自动处理冲突检测和解决方案。当然,每次改变时你都不想创建一个新的MOC;如果您不介意UI的某些部分在其他部分发现未保存的更改(MOC间通信的开销可忽略不计),那么通过缓慢的“用户线程”让未保存的更改有一个MOC可能是非常明智的。

+0

嗨@tc。我尝试了第一个是insertIntoManagedObjectContext的响应:nil,但是当我想分配一个关系时,应用程序崩溃了:reason:'非法尝试在不同上下文中的对象之间建立关系“类别”。所以我想我的问题是因为它是不合法的上下文NSManaged对象和上下文管理对象之间的关系,什么是解决方案? – 2010-10-06 14:09:38

+0

我最终创建了一个类别实体没有上下文相同的方式,但是当它来保存我添加到上下文,然后它运作良好。 – 2010-10-06 14:31:04

+2

我可以证实此答案的正确性。我刚刚遇到了一个与上下文无关的问题。添加上下文之前分配给对象的属性值在最终将对象添加到子上下文时不会传播到父上下文。属性在持久性存储中以“nil”存储。当我切换顺序时(即在将属性值插入上下文之后赋值),事情正常运行。这个故事的道德观点是,没有上下文的情况下实例化一个对象并不是一个好主意。 – 2014-03-21 07:06:38

您可以插入NSManagedObjectContext-[NSManagedObject initWithEntity:insertIntoManagedObjectContext:],传递nil作为托管对象上下文。当然,你必须将它分配给上下文(在保存之前使用-[NSManageObjectContext insertObject:]),但据我所知,这并不是Core Data中的预期模式(但请参阅@ mzarra的回答here)。有一些棘手的排序问题(例如确保实例在预期有上下文之前被分配给上下文等)更为标准的模式是创建一个新的托管对象上下文并将新对象插入该上下文当用户保存时,保存并处理NSManagedObjectDidSaveNotification将这些更改合并到您的“主要”上下文中。如果用户取消交易,您只需吹掉背景并继续与您的业务相关即可。

+0

我想你的意思'NSManagedObject',不'NSManagedObjectContext'。无论哪种方式,它看起来并不像你可以改变一个NSManagedObject与—关联,您可能使用'会混淆它的MOC - [的NSManagedObjectContext assignObject:toPersistentStore:]'。 – 2010-10-06 00:09:04

+0

@tc,感谢您的错字捕捉。 – 2010-10-06 01:12:10

对于它的价值,Marcus Zarra似乎要推广nil上下文方法,声称创建一个新的上下文是昂贵的。 ls,参见this answer也有类似的问题。

我目前使用的无背景的办法也碰到了一些可能会感兴趣的其他更新。要创建没有上下文的管理对象,请使用NSManagedObjectinitWithEntity:insertIntoManagedObjectContext:方法。根据Apple对此方法的文档:

If context is not nil , this method invokes [context insertObject:self] (which causes awakeFromInsert to be invoked).

这里的含义很重要。在创建管理对象时使用nil上下文将阻止insertObject:被调用,并因此阻止awakeFromInsert被调用。因此,当使用nil上下文时,在awakeFromInsert中完成的任何对象初始化或默认属性值设置都不会自动发生。底线:使用不带上下文的管理对象时,awakeFromInsert不会自动调用,您可能需要额外的代码才能进行补偿。

+0

嗨这工作了一段时间,直到我试图建立我的事务和NSManagedObject类别之间的关系。那么应用程序就会因此而崩溃。有没有办法解决它? – 2010-10-06 14:14:26

+0

如果你需要建立关系,我会采用两种背景方法。作为tc。指出,不同上下文中的对象不应该相互引用。另一方面,您可以推迟设置这些关系,直到*将新的未关联对象插入主要上下文之后。 – 2010-10-06 15:44:49

这里是我的工作了:

上的负载,我们知道我们面对的是一个新的事务,我创建了一个断章取义之一。

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; 
     transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

那么,当它来建立关系,船我这样做:

if(transaction.managedObjectContext == nil){ 
     NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext]; 
     Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 
     category.title = ((Category *)obj).title; 
     transaction.category = category; 
     [category release]; 
    } 
    else { 
     transaction.category = (Category *)obj; 
    } 

,并在年底节省:

if (transaction.managedObjectContext == nil) { 
     [self.managedObjectContext insertObject:transaction.category]; 
     [self.managedObjectContext insertObject:transaction]; 
    } 
    //NSLog(@"\n saving transaction\n%@", self.transaction); 

    NSError *error; 
    if (![self.managedObjectContext save:&error]) { 
     // Update to handle the error appropriately. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); // Fail 
    } 
+0

我想知道我是否可以做... transaction =(Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@“Transaction”inManagedObjectContext:context];然后transaction.managedObjectContext = nil;那会是错的吗? – yunas 2012-09-11 09:41:40

的NSManagedObject可以使用零作为创建上下文,但如果有其他NSManagedObjects它必须链接到它将导致错误。我这样做的方式是将上下文传递到目标屏幕,并在该屏幕中创建一个NSManagedObject。使所有更改链接其他NSManagedObjects。如果用户点击取消按钮,我删除NSManagedObject并保存上下文。如果用户点击保存按钮,我更新NSManagedObject中的数据,将其保存到上下文中,然后释放屏幕。在源屏幕中,我使用重新加载来更新表格。

删除NSManagedObject在目的地屏幕给出了核心数据的时间来更新文件。这通常足以让你在tableview中看不到变化。在iPhone日历应用程序中,从节省的时间到显示在桌面视图中的时间都有延迟。从UI的角度来看,这可能被认为是一件好事,您的用户将专注于刚添加的行。我希望这有帮助。

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil]; 

如果最后一个参数是零,它会返回一个NSManagedObject没有保存到数据库

+0

这将导致失败:***终止应用程序,由于未捕获异常'NSInvalidArgumentException',原因:'+ entityForName:nil不是合法的NSManagedObjectContext参数搜索实体名称... – c9s 2015-03-12 12:53:09