如何防止连续的autosaveInPlace连续更新值绑定选项

时间:2011-11-21 22:40:48

标签: cocoa osx-lion

持续更新值绑定选项会触发连续的autosaveInPlace尝试(对于您键入的每个字符)。

大家好,这是我的第一个问题!

我希望我能正确地问它......:)

我正在尝试将Lion的自动保存机制添加到我的基于核心数据文档的应用程序中。 在我的NSPersistentDocument子类中,我重写+(BOOL)autosaveInPlace方法,返回YES并且所有功能都正常工作(保存,新菜单,版本浏览器......)。

我的问题是,当我使用持续更新值选项键入绑定到我的模型的文本字段时,自动保存系统会在每次单击时触发保存操作!旋转的沙滩球没有出现(也许是因为我的文件相当小)但打字真的很慢。

每次按键都会调用

AutosaveInPlace,然后调用saveToURL…writeToURL…方法。

我发现网上的主题几乎没有,甚至在Apple的官方文档中也没有。

在自动保存和版本WWDC '11视频中,工程师提供了一个不完整的示例,说明当[self autosavingIsImplicitlyCancellable]返回YES时如何取消自动保存,但在我的情况下,此方法始终返回{{1 }}。这必须是预期的行为:必须不断更新该值,并且由于磁盘文件必须始终与用户在屏幕上看到的内容相同,因此不得取消此保存。

我在网上找到了一个更有用的例子,说明如何防止首先启动保存(使用NO方法而不是save…方法)。

write…

这很有效。在自动保存的情况下,如果我的文本字段具有焦点,我将记录的静默可可错误传递给完成处理程序并且不会发生保存,UI像以前一样响应。原始海报声称,通过这种方式,自动保存实际上会延迟到当前活动结束,但我不确定。

我的问题是我不想观察开始/结束编辑的每一个文本字段,并且必须不时地自己手动触发自动保存,因为我阻止系统在我做的时候这样做我在文本字段中写作。系统应该理解,在单击键的基础上触发保存是不合理的。

在WWDC '11视频中,工程师指出了通过 -(void)saveToURL:(NSURL *)url ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation completionHandler:(void (^)(NSError *errorOrNil))completionHandler { if (saveOperation == NSAutosaveInPlaceOperation) { if ([self isWritingInMyTextField]) { completionHandler([NSError errorWithDomain:NSCocoaErrorDomain code:NSUserCancelledError userInfo:nil]); return; } } [super saveToURL:url ofType:typeName forSaveOperation:saveOperation completionHandler:completionHandler]; } 和事件检查用户活动的方法,但这远远超出了我的理解。我搜索了NSRunLoopNSRunLoop的文档,但我无法弄清楚如何获取“用户主动输入内容的信息!”。

如果有人能指出我在这个主题上的正确方向,我将不胜感激。

如果有人知道处理这个问题的推荐方法会更好!

作为最后的考虑,我可以在NSPersistentDocument的文档中读到«NSPersistentDocument不支持NSDocument的异步保存API,因为该API需要在多个线程上访问文档的状态并且违反了NSManagedObjectContext的要求。»这是否意味着除非您的应用程序文档非常小,否则您根本不应该使用自动保存? 好吧,Apple似乎希望自动保存成为所有新应用程序的新方式,所以如果开发人员必须放弃核心数据,我无法弄清楚它是如何发生的。

2 个答案:

答案 0 :(得分:2)

这是我的工作答案。

+(BOOL)autosavesInPlace { return YES; }

-(BOOL)isUserTyping {

    NSUInteger eventType = [[NSApp currentEvent] type];
    return (eventType == NSKeyDown ||
            eventType == NSKeyUp ||
            eventType == NSFlagsChanged);
}

-(void)saveToURL:(NSURL *)url
          ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
completionHandler:(void (^)(NSError *errorOrNil))completionHandler {

    if (saveOperation == NSAutosaveInPlaceOperation) {

        if ([self isUserTyping]) {

            completionHandler([NSError errorWithDomain:NSCocoaErrorDomain
                                                  code:NSUserCancelledError
                                              userInfo:nil]);

            return;
        }
    }

    [super saveToURL:url ofType:typeName forSaveOperation:saveOperation completionHandler:completionHandler];
}

我不知道我的isUserTyping方法是否是最好的方法。 WWDC '11视频工程师使用运行循环检查用户活动对我来说仍然是一个谜!

答案 1 :(得分:0)

我认为您需要覆盖-scheduleAutosaving的{​​{1}}方法,并阻止它在您的文本字段处于活动状态时执行任何操作。

此方法的文档说明:

  

此方法的默认实现检查是否自动保存   已启用,如果是,并且[self hasUnautosavedChanges]返回   是,安排NSTimer调用   autosaveDocumentWithDelegate:didAutosaveSelector:contextInfo:in   将来

...

  

您可以覆盖此方法以控制何时发生确切的定期自动保护。

我建议做这样的事情:

NSDocument

请注意,我不确定这是否有效,因为文档说明计时器已安排进行自动保存,我不知道是否可以获取该计时器的句柄,以便您可以取消计划。