cocoa - 如何通过不断更新值绑定(bind)选项来防止连续 autosaveInPlace

标签 cocoa osx-lion

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

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

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

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

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

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

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

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

我在网上找到了一个更有用的示例,说明如何从一开始就阻止保存(ovverriding 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];
}

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

我的问题是,我不想观察每个文本字段以进行开始/结束编辑,并且必须时不时地手动触发自动保存,因为我阻止系统在我执行此操作时执行此操作。我在文本字段中书写。系统应该明白在单次击键的基础上触发保存是不合理的。

在 WWDC ’11 视频中,工程师指出了一种通过 NSRunLoop 和事件检查用户事件的方法,但这远远超出了我的理解范围。我搜索了 NSRunLoopNSEvent 的文档,但我不知道如何获取信息“用户正在主动输入内容!”。

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

如果有人知道处理此问题的推荐方法,那就更好了!

作为最后一个考虑因素,我可以在 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 视频工程师使用运行循环来检查用户事件对我来说仍然是个谜!

关于cocoa - 如何通过不断更新值绑定(bind)选项来防止连续 autosaveInPlace,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8219557/

相关文章:

macos - 从 OSX 10.6 切换到 10.7 时出现 Scons 编译错误

macos - 较少编译为空的 CSS 文件

python - 如何在 OSX Lion 下独立于/System/Library/Frameworks 安装 Python 2.7.x?

Lion 上的 MYSQL - 设置 root 密码

objective-c - 这是安全/有效的哈希方法实现吗?

c - 我如何在 OS X Lion 上获得 GCC?

objective-c - 核心数据获取仅返回唯一的托管对象

objective-c - 如何将事件对象添加到 NSMutableArray 并在它们被释放时删除它们?

swift - 如何使用 NSVisualEffectView 将窗口与背景混合

ios - NSOperation 依赖操作和依赖对象