我想创建一个iPhone应用程序,用户可以添加条目。当他按下一个新条目,弹出对话框提示,询问他的一些信息。然后,他可以按“取消”或“保存”丢弃该数据或将其保存到磁盘。

有关节能,我使用的是Core Data框架,它工作得很好。但是,我不能得到的“取消”按钮的工作。当窗口弹出,询问信息,我创建了管理对象上下文(MOC)的新对象。然后,当用户按下取消,我尝试使用属于MOC的NSUndoManager。

我也想做到这一点使用嵌套撤消群体,因为有可能是嵌套组。

要测试这一点,我写了一个简单的应用程序。该应用程序只是“基于Windows的应用程序”模板,使核心数据。对于核心数据模型,我创建一个名为“实体”与整数属性“×”的单一实体。则的applicationDidFinishLaunching内,我添加以下代码:

- (void)applicationDidFinishLaunching:(UIApplication *)application {    

  // Override point for customization after app launch    

  unsigned int x=arc4random()%1000;
  [self.managedObjectContext processPendingChanges];
  [self.managedObjectContext.undoManager beginUndoGrouping];

  NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity" 
                                                        inManagedObjectContext:self.managedObjectContext];
  [entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
  NSLog(@"Insert Value %d",x);

  [self.managedObjectContext processPendingChanges];
  [self.managedObjectContext.undoManager endUndoGrouping];
  [self.managedObjectContext.undoManager undoNestedGroup];

  NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
  NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
                                                inManagedObjectContext:self.managedObjectContext];
  [fetchRequest setEntity:entityEntity];
  NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
  for(entity in result) {
    NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
  }

    [window makeKeyAndVisible];
}

的思想很简单。尝试插入一个新的实体对象,撤消,获取所有实体在MOC对象并打印出来。如果一切运行正常,应该在年底没有对象。

不过,我得到这样的输出:

[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 Untitledundotes[7373:20b] Insert Value 136
2010-02-20 13:41:51.715 Untitledundotes[7373:20b] FETCHED ENTITY 136

正如你所看到的,对象是存在于MOC后,我试图解开它的创作。 任何建议,我在做什么错了?

有帮助吗?

解决方案

您的问题是,不同于OS X,iPhone的管理对象范围内不包含默认的撤消管理造成的事实。您需要明确地添加一个。

变化应用程序委托用于managedObjectContext属性生成的代码看起来像这样:

- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] init];
        //add the following 3 lines of code
        NSUndoManager *undoManager = [[NSUndoManager alloc] init];
        [managedObjectContext setUndoManager:undoManager];
        [undoManager release];
        [managedObjectContext setPersistentStoreCoordinator: coordinator];
    }

    return managedObjectContext;

}

做出这样的转变后,将第二日志消息不再打印。

希望帮助...

戴夫

其他提示

我试过戴夫的做法,但对我没有工作。 我终于找到了在苹果的例子 CoreDataBooks

关键是要创建一个新的背景下,与您分享的协调应用的上下文。要放弃你不需要做任何事情的变化,只是丢弃新的上下文对象。既然你分享的协调,节省您的更新主要内容。

下面是我的适配版本,其中,我使用的静态对象用于临时上下文来创建一个新对象ChannelMO

//Gets a new ChannelMO that is part of the addingManagedContext
+(ChannelMO*) getNewChannelMO{

    // Create a new managed object context for the new channel -- set its persistent store coordinator to the same as that from the fetched results controller's context.
    NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
    addingManagedObjectContext = addingContext;

    [addingManagedObjectContext setPersistentStoreCoordinator:[[self getContext] persistentStoreCoordinator]];

    ChannelMO* aux = (ChannelMO *)[NSEntityDescription insertNewObjectForEntityForName:@"ChannelMO" inManagedObjectContext:addingManagedObjectContext];
    return aux;
}

+(void) saveAddingContext{
    NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
    [dnc addObserver:self selector:@selector(addControllerContextDidSave:) 
                name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];

    NSError *error;
    if (![addingManagedObjectContext save:&error]) {
        // Update to handle the error appropriately.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        exit(-1);  // Fail
    }
    [dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:addingManagedObjectContext];

    // Release the adding managed object context.
    addingManagedObjectContext = nil;
}

我希望它能帮助

Gonso

它应该工作。您是否正确撤消管理分配给您的managedObjectContext?如果你已经正确地在默认情况下做到这一点,它启用了撤消注册,你应该是好去。有核心数据这里好文章。有核心数据和NSUndoManager 这里一个很好的教程。希望有所帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top