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



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

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

我希望我能正确地问…:)

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

我的问题是,当我输入文本字段绑定到我的模型与不断更新的值选项,自动保存系统触发保存操作在每一个按键!旋转的沙滩球没有出现(可能是因为我的文档相当小),但是打字真的很慢。

每次按下键都调用AutosaveInPlace,随后调用saveToURL…writeToURL…方法。

我在网上几乎找不到关于这个主题的任何信息,在苹果公司的官方文档中就更少了。

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

我在网上找到了一个更有用的例子,如何防止保存被初始化(覆盖save…方法而不是write…方法)。

 -(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];
}

这是工作。在自动保存的情况下,如果我的textfield有焦点,我将记录的沉默的cocoa错误传递给完成处理程序,保存不会发生,UI像以前一样响应。原来的海报声称,在这种方式下,自动保存实际上是延迟到当前活动结束,但我不确定。

我的问题是,我不想要观察每一个文本字段开始/结束编辑,不得不手动触发自动保存自己,每隔一段时间,因为我阻止系统这样做,而我在文本字段中写作。系统应该明白在一次击键的基础上触发保存是不合理的。

在WWDC ' 11视频中,工程师指出了一种通过NSRunLoop和事件检查用户活动的方法,但这远远超出了我的理解。我搜索了NSRunLoop, NSEvent的文档,但我不知道如何获得信息«用户正在积极键入一些东西!»。

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

如果有人知道处理这个问题的建议方法就好了!

作为最后的考虑,我可以在NSPersistentDocument的文档中读到«NSPersistentDocument不支持NSDocument的异步保存API,因为该API需要在多个线程上访问文档的状态,这违反了NSManagedObjectContext的要求。»这是否意味着除非你的应用文档非常小,否则你根本不应该使用自动保存功能?好吧,苹果似乎想让自动保存成为所有新应用的新方式,所以如果开发者必须放弃核心数据,我不知道这怎么可能发生。

这是我的工作答案。

+(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视频工程师使用运行循环来检查用户活动对我来说仍然是一个谜!

我认为你需要覆盖NSDocument-scheduleAutosaving方法,并防止它做任何事情,而你的文本字段是活跃的。

这个方法的文档状态:

此方法的默认实现检查是否自动保存是打开的,如果是,如果[self hasUnautosavedChanges]返回是的,调度要调用的ntimerautosaveDocumentWithDelegate:didAutosaveSelector:contextInfo未来。

您可以重写此方法以控制何时精确地周期性自动保存。

我建议这样做:

- (void)scheduleAutosaving
{
    if([self checkIfOneOfYourTextFieldsIsActive])
         return;
    //no text field is active, so just use the default behaviour
    [super scheduleAutosaving];
}

请注意,我不确定这是否会起作用,因为文档声明定时器被安排做自动保存,我不知道是否有可能得到定时器的处理,以便您可以取消它

最新更新