2011-11-21 47 views
2

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

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

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

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

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

AutosaveInPlace被称为每按键,然后saveToURL…writeToURL…方法。

在网络上我几乎没有发现任何问题,甚至在Apple官方文档中也没有发现。

在自动保存和版本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]; 
} 

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

我的问题是,我不希望必须观察每一个文本字段的开始/结束编辑,并且必须手动触发一个自动保存我自己每隔一段时间,因为我阻止系统做它,而我正在写文本字段。系统应该明白,在单个按键的基础上触发保存是不合理的。

在WWDC '11视频中,工程师指出通过NSRunLoop和事件检查用户活动的方式,但这远远超出我的理解范围。我搜索了文档NSRunLoop,NSEvent,但我无法弄清楚如何获取信息«用户主动输入内容!»。

如果有人能指出我在这个主题的正确方向,我会很感激。

如果有人知道推荐的处理这个问题的方法会更好!作为最后的考虑,我可以在NSPersistentDocument的文档中看到“NSPersistentDocument不支持NSDocument的异步保存API,因为该API需要访问多线程上的文档状态,并且违反了NSManagedObjectContext的要求”。这是否意味着,除非你的应用程序的文档很小,否则根本不应该使用自动保存? 好吧,苹果似乎希望autosave成为所有新应用程序的新事物,所以我无法弄清楚如果开发人员必须放弃核心数据才会发生这种情况。

+1

为什么不重写autosavingIsImplicitlyCancellable以返回YES? – sosborn

+0

我会试试看,谢谢! – wdyp

回答

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

+0

在Cocoa中,通常每个窗口只有一个“字段编辑器”从一个字段跳转到另一个字段,因为用户焦点始终位于单个特定字段上。因此,您可以询问现场编辑器,而不是观察每个字段。 –

0

我相信你需要覆盖-scheduleAutosaving方法NSDocument,并防止它在你的文本字段处于活动状态时做任何事情。

此方法状态的文档:

此方法检查的默认实现,以查看是否自动保存 导通,并且,如果是这样,并且如果[自hasUnautosavedChanges]返回 YES,调度一个NSTimer到调用 autosaveDocumentWithDelegate:didAutosaveSelector:contextInfo:将来的 。

...

您可以覆盖此方法时,正是定期自动保存情况来控制。

我建议做这样的事情:

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

请注意,我不知道这是否会工作,因为文档指出,一个计时器被安排做自动保存和我不t知道是否有可能获得该计时器的句柄,以便您可以不计划它。

+0

谢谢,我会尝试覆盖autosavingIsImplicitlyCancelable和/或scheduleDotosaving今晚... 阅读文档我认为scheduleAutosaving是一种旧的方法,可能不适用于新的自动保存(因为现在它不仅取决于定时器,而且还发生在各种场合),但你可能是对的。我迫不及待想要发布结果。 – wdyp

+0

好吧,scheduleAutosaving的确是一种全新的Lion方法,但是这种重写本身并不会阻止用户输入不断更新的值文本字段时发生自动保存。 该文档指出:“为了*碰撞保护的目的,安排周期性自动保存*。”我认为不断更新值会告诉系统该值应立即提交。这些自动保存事件不是由计时器触发的,而是在每次按键时发生。 – wdyp