2013-03-08 37 views
4

我在我的應用程序的Documents目錄上有一個kQueue觀察者。我正在使用在文檔目錄內容更改時觸發回調的kQueue。kQueue目錄監控

這裏有兩個設置

eventToAdd.flags = EV_ADD | EV_CLEAR; 
eventToAdd.fflags = NOTE_WRITE; 

的問題是,我得到通知,當內容發生變化時增加了一個新的文件,但實際的文件還沒有完全複製,所以當我嘗試的過程新文件我得到一個SIGABRT崩潰。

如何推遲通知,直到文件完成?

回答

2

我解決了這個問題,方法是創建兩個監聽器...一個在應用程序的Documents目錄中以監視新文件的出現以及爲每個出現的文件創建的File代理對象。 File對象有一個fileBusy標誌。當大塊數據寫入文件時,File對象設置2秒計時器。如果在定時器到期之前沒有更新,我認爲文件是完全寫入的。

文件更改監聽器代碼在這裏:https://gist.github.com/nielsbot/5155671

我的(部分)委託低於上述監聽器。 (表示文件在磁盤上的「文件」對象)

@implementation File<FileChangeObserverDelegate> 

    -(void)scheduleFileBusyTimeout 
    { 
     self.fileBusyTimeoutTimer = [ NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(fileBusyTimeoutTimerFired:) userInfo:nil repeats:NO ] ; 
    } 

    -(void)setFileChangeObserver:(FileChangeObserver *)observer 
    { 
     [_fileChangeObserver invalidate ] ; 
     _fileChangeObserver = observer ; 
    } 

    -(void)fileChanged:(FileChangeObserver *)asset typeMask:(enum FileChangeNotificationType)type 
    { 
     @synchronized(self) 
     { 
      if ((type & kFileChangeType_Delete) != 0) 
      { 
       // we're going away soon... 
       self.fileChangeObserver = nil ; 
      } 
      else 
      { 

       self.fileBusy = YES ; 
       [ self scheduleFileBusyTimeout ] ; 
      } 
     } 
    } 

    -(void)fileBusyTimeoutTimerFired:(NSTimer*)timer 
    { 
     @autoreleasepool { 
      self.fileBusy = NO ; 
     } 
    } 

    -(void)setFileBusyTimeoutTimer:(NSTimer *)timer 
    { 
     [ _fileBusyTimeoutTimer invalidate ] ; 
     _fileBusyTimeoutTimer = timer ; 
    } 
@end 
+0

謝謝你。我會盡快嘗試並回復你。 – jarryd 2013-03-13 22:15:11

0

首先,請參閱:

簡短的回答是,沒有很好的方法來做到這一點。理想情況下,您應該將文件寫入其他位置,然後將其移至文檔中。這使其成爲原子行動。或者把它寫成一個特殊的文件名(「.partial」,「.download」等),並在最後重命名(同樣是一個會觸發第二個kqueue事件的原子動作)。

+0

我喜歡'.partial'概念 - 儘管如果你通過iTunes放入文件,它不會遵守這個規則。我的解決方法是在每次寫入文件後設置一個計時器,然後假定該文件在1秒左右後完全寫入。 – nielsbot 2013-03-13 20:16:36

+0

@nielsbot - 是1秒左右嗎?添加文件名時是否觸發事件,並且根據文件大小,寫操作是動態的,並且定時不可知。 – jarryd 2013-03-13 21:02:07

+0

每次將_new chunk_寫入文件時,您將收到一條kqueue通知 - 在每個chunk_之後將您的計時器重置爲1秒。 1s計時器不適用於整個文件寫入。如果沒有組塊被寫入1s的持續時間,假定文件被完全寫入。我不明白,但我知道,但我想不出更好的辦法。 – nielsbot 2013-03-13 21:30:45