有没有办法实例化NSManagedObject而不插入它?

Edw*_*hak 54 iphone core-data nsfetchedresultscontroller nsmanagedobject

我有一个用户界面来插入一个Transaction.一旦用户点击加号,他就会获得屏幕,我想要实例化我的核心数据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]
Run Code Online (Sandbox Code Playgroud)

PS我在该表上使用NSFetchedResultsController,我看到NSFetchedResultsController正在向表中插入一个节和一个对象.

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

Jam*_*ton 37

对于它的价值,Marcus Zarra似乎正在推广nil上下文方法,声称创建新上下文的成本很高.有关详细信息,请参阅此问题的答案.

更新

我目前正在使用nil上下文方法,并遇到了其他人可能感兴趣的内容.要创建没有上下文的托管对象,请使用initWithEntity:insertIntoManagedObjectContext:方法NSManagedObject.根据Apple针对此方法的文档:

如果context不是nil,则此方法调用[context insertObject:self] (导致awakeFromInsert调用).

这里的含义很重要.nil在创建托管对象时使用上下文将阻止insertObject:被调用,从而防止awakeFromInsert被调用.因此,awakeFromInsert在使用nil上下文时,任何对象初始化或完成的默认属性值的设置都不会自动发生.

结论:当使用没有上下文的托管对象时,awakeFromInsert不会自动调用,您可能需要额外的代码来补偿.


Edw*_*hak 19

这是我如何解决的问题:

在加载时,我们知道我们正在处理一个新事务,我创建了一个脱离上下文的事务.

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

然后,在建立关系船时,我这样做了:

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;
    }
Run Code Online (Sandbox Code Playgroud)

并在最后保存:

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
    }
Run Code Online (Sandbox Code Playgroud)


tc.*_*tc. 17

使用零MOC存在一个基本问题:不同MOC中的对象不应该相互引用 - 这可能也适用于关系的一方没有MOC的情况.如果你保存会怎么样?(当您的应用的另一部分保存时会发生什么?)

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

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

然而,使用第二个MOC是"假设"使用CoreData的方式; 它会自动处理冲突检测和解决方案.当然,每次发生变化时,您都不希望创建新的MOC; 如果您不介意UI的某些部分在其他部分看到未保存的更改(MOC间通信的开销可以忽略不计),则缓慢的"用户线程"为未保存的更改提供一个MOC可能是模糊不清的.

  • 我可以证明这个答案的正确性.我刚刚得到一个与对象的上下文为零有关的问题.在添加上下文之前分配给对象的属性值在最终将对象添加到子上下文时不会传播到父上下文.属性在持久性存储中存储为"nil".当我切换顺序(即在将其插入上下文后分配属性值)时,事情正常.故事的道德是,在没有上下文的情况下实例化对象并不是一个好主意. (2认同)

Bar*_*ark 8

您可以插入一个NSManagedObjectContextwith -[NSManagedObject initWithEntity:insertIntoManagedObjectContext:],传递nil给托管对象上下文.你必须,当然,它分配给一个上下文(使用-[NSManageObjectContext insertObject:]保存前然而,这是,据我所知,没有真正的意图核心数据模式(但见@ mzarra的答案在这里).有一些棘手的排序问题(即确保实例在期望有一个上下文之前被分配给上下文等.)更标准的模式是创建一个新的托管对象上下文并将新对象插入到该上下文中.当用户保存时,保存上下文,并处理NSManagedObjectDidSaveNotification将更改合并到您的"主要"上下文.如果用户取消交易,您只需吹走上下文并继续您的业务.