GCDを使用したファイルの監視

ほとんどのiOS開発者は、Info.plistに1行だけ追加するだけで、アプリケーションでiTunesファイル共有を簡単に有効にする方法を知っていると思います。
UIFileSharingEnabled = YES
      
      



しかし、これは戦いの半分でもありません。 重要な点は、良い方法で、アプリケーションはDocumentsディレクトリで発生したファイルへのすべての変更を追跡し、それに応じてデータを更新する必要があることです。 この記事では、コードでこれをリリースする方法を説明します。

画像



そもそも、Concurrency Programming Guideのかなりの理論です。 GCDには、 ディスパッチソースなどの概念があります。これは、特定の低レベルイベントの処理を調整する基本的なデータ型です。 問題を解決するために、ファイルやソケットを使用したさまざまな操作について通知する記述子ソースとして、そのようなバリエーションに最も関心があります。



dispatch_source_create



メソッドを使用してディスパッチマネージャを作成する必要があります。このメソッドのソースはファイル記述子(ディレクトリファイル記述子)であり、イベント自体(ファイルの記録)によって必要なアプリケーションデータ更新ブロックを実行します。



ここで、イベントはディスクに書き込まれたファイルの最初のバイトによってトリガーされ、ファイルが大きくなっていることに注意する必要があります。 したがって、データ更新ブロックでは、1秒のタイムアウトで同期の終了の再帰的なチェックを開始します。



だから、体に近い。 必要なディレクトリの監視を開始および停止する2つの主要なメソッドstartMonitor



stopMonitor



を作成します。また、ハンドラーブロックを介して起動されるこのディレクトリの変更をチェックするための補助メソッドをいくつか作成します。



 - (void)startMonitor { //     dispatch_source_t if (_src != NULL) return; //    Documents   NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; //  ,     (O_EVTONLY) _fileDescriptor = open([docPath fileSystemRepresentation], O_EVTONLY); //    thread,     UI dispatch_queue_t queue = dispatch_get_main_queue(); //    dispatch source    (write) _src = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, _fileDescriptor, DISPATCH_VNODE_WRITE, queue); // handler block      dispatch_source_set_event_handler(_src, ^{ [self directoryDidChange]; }); //     dispatch_source_set_cancel_handler(_src, ^{ close(_fileDescriptor); }); dispatch_resume(_src); } - (void)stopMonitor { if (_src) { //   ,    dispatch_source_cancel(_src); _src = NULL; } } - (void)directoryDidChange { if(!waitingForDocumentsDirectoryTimeout) { // ,    ,     waitingForDocumentsDirectoryTimeout = YES; //       _lastDocumentsDirectoryReferenceArray=[self documentsDirectoryReferenceArray]; //...         ,  [self performSelector:@selector(checkForDocumentsDirectoryChanges) withObject:nil afterDelay:1.0 inModes:[NSArray arrayWithObjects:NSRunLoopCommonModes,nil]]; } } -(void)checkForDocumentsDirectoryChanges { NSArray *newDocumentsDirectoryReferenceArray=[self documentsDirectoryReferenceArray]; //      if(![newDocumentsDirectoryReferenceArray isEqualToArray:_lastDocumentsDirectoryReferenceArray]) { //       _lastDocumentsDirectoryReferenceArray=newDocumentsDirectoryReferenceArray; [self performSelector:@selector(checkForDocumentsDirectoryChanges) withObject:nil afterDelay:1.0 inModes:[NSArray arrayWithObjects:NSRunLoopCommonModes,nil]]; } else { //    waitingForDocumentsDirectoryTimeout=NO; _lastDocumentsDirectoryReferenceArray=nil; // ...         ,  [self scanDocumentsDirectory]; } } -(NSArray *)documentsDirectoryReferenceArray { //         - NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSArray *documentsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectoryPath error:NULL]; NSMutableArray *documentsDirectoryReferenceArray=[NSMutableArray arrayWithCapacity:10]; for(NSString *fileName in documentsDirectoryContents){ NSString *filePath=[documentsDirectoryPath stringByAppendingPathComponent:fileName]; NSError *error; NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error]; NSInteger fileSize = [[fileAttributes objectForKey:NSFileSize] intValue]; NSString *fileWithLength=[NSString stringWithFormat:@"%@-%d",fileName,fileSize]; [documentsDirectoryReferenceArray addObject:fileWithLength]; } return documentsDirectoryReferenceArray; }
      
      







さて、テキストに目を向け、理解するのが面倒な人のために、同様のアプローチがCocoanetics / DTFoundationクラスDTFolderMonitor



で既に実装されています。



また、iTunesファイル共有を使用してアプリケーションを操作した経験から、アプリケーションがアクティブになったらすぐに、監視に加えてscanDocumentsDirectory



などのメソッドを実行する必要があることを思い出したいと思います。 その目的は、チェックするだけでなく、ディレクトリ内の実際の存在を使用してアプリケーション内のファイルのデータを更新することでもあります。



 - (void)applicationWillEnterForeground:(UIApplication *)application { [self scanDocumentsDirectory]; }
      
      







ソースへの参照
Apple Developers Forumのトピックに関する歴史的なディスカッションスレッド (アクセスするには開発アカウントが必要です)

ディレクトリモニター -Michael HeyeckによるOld School Monitor

ディレクトリモニタリングとGCDは同じですが、更新されています

SocoaneticsのGCDソリューションでフォルダーを監視する




All Articles