8

David Hamrickによるコード例を使用して、GCD を使用してファイルを監視しています。

int fildes = open("/path/to/config.plist", O_RDONLY);

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fildes, 
                                                  DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE,
                                                  queue);
dispatch_source_set_event_handler(source, ^
{
    //Reload the config file
});
dispatch_source_set_cancel_handler(source, ^
{
    //Handle the cancel
});
dispatch_resume(source);

plistの変更を監視するために使用したい。最初の変更後に通知を受け取りますが、次の変更については受け取りません。なんで?

4

2 に答える 2

11

実際、DISPATCH_VNODE_DELETE を受け取ったときに、ファイルを再度開いてソースを再登録する (前のソースを削除する) ことができます。または、この種のシナリオ用に考案された呼び出し、つまりdispatch_io_create_with_path()を使用できます。これは、パスで監視するだけでなく、ファイルを開き、内容を非同期で読み取ることができます。

あなたが尋ねたので(あなたが求めたテクニックはわかりませんが、これが最も簡単です)、スタンドアロンのコードサンプルを次に示します。

#include <dispatch/dispatch.h>
#include <stdio.h>

int main(int ac, char *av[])
{
  int fdes = open("/tmp/pleasewatchthis", O_RDONLY);
  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
  void (^eventHandler)(void), (^cancelHandler)(void);
  unsigned long mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
  __block dispatch_source_t source;

  eventHandler = ^{
    unsigned long l = dispatch_source_get_data(source);
    if (l & DISPATCH_VNODE_DELETE) {
      printf("watched file deleted!  cancelling source\n");
      dispatch_source_cancel(source);
    }
    else {
      // handle the file has data case
      printf("watched file has data\n");
    }
  };
  cancelHandler = ^{
    int fdes = dispatch_source_get_handle(source);
    close(fdes);
    // Wait for new file to exist.
    while ((fdes = open("/tmp/pleasewatchthis", O_RDONLY)) == -1)
      sleep(1);
    printf("re-opened target file in cancel handler\n");
    source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fdes, mask, queue);
    dispatch_source_set_event_handler(source, eventHandler);
    dispatch_source_set_cancel_handler(source, cancelHandler);
    dispatch_resume(source);
  };

  source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fdes, mask, queue);
  dispatch_source_set_event_handler(source, eventHandler);
  dispatch_source_set_cancel_handler(source, cancelHandler);
  dispatch_resume(source);
  dispatch_main();
}
于 2012-07-07T05:13:29.270 に答える
2

少し調べた後、私は見つけました:

=>私は旗を手に入れていましたDISPATCH_VNODE_DELETE

監視~/Library/Preferences/com.apple.dock.plistしていたのですが、ドックの向きを変更すると、元のファイルが削除され、新しいファイルに置き換えられます。

そのため、監視を停止しました。

同じ作成者は、削除の場合にGCDブロックがそれ自体を呼び出して監視を続行するソリューションを提案しています。

于 2012-07-06T02:57:48.033 に答える