2013-03-08 38 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