持续更新值绑定选项会触发连续的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];
}
和事件检查用户活动的方法,但这远远超出了我的理解。我搜索了NSRunLoop
,NSRunLoop
的文档,但我无法弄清楚如何获取“用户主动输入内容的信息!”。
如果有人能指出我在这个主题上的正确方向,我将不胜感激。
如果有人知道处理这个问题的推荐方法会更好!
作为最后的考虑,我可以在NSPersistentDocument的文档中读到«NSPersistentDocument不支持NSDocument的异步保存API,因为该API需要在多个线程上访问文档的状态并且违反了NSManagedObjectContext的要求。»这是否意味着除非您的应用程序文档非常小,否则您根本不应该使用自动保存? 好吧,Apple似乎希望自动保存成为所有新应用程序的新方式,所以如果开发人员必须放弃核心数据,我无法弄清楚它是如何发生的。
答案 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
请注意,我不确定这是否有效,因为文档说明计时器已安排进行自动保存,我不知道是否可以获取该计时器的句柄,以便您可以取消计划。