持续更新值绑定(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 和事件检查用户事件的方法,但这远远超出了我的理解范围。我搜索了 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 视频工程师使用运行循环来检查用户事件对我来说仍然是个谜!
关于cocoa - 如何通过不断更新值绑定(bind)选项来防止连续 autosaveInPlace,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8219557/