2011-11-21 33 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