4

アプリのDocumentsディレクトリにkQueueオブザーバーがあります。Documentsディレクトリの内容が変更されたときにコールバックをトリガーするkQueueを使用しています。

ここに2つの設定があります

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

問題は、新しいファイルが追加されたときに内容が変更されたときに通知を受け取ることですが、実際のファイルはまだ完全にコピーされていないため、新しいファイルを処理しようとするとSIGABRTがクラッシュします。

ファイルが完了するまで通知を遅らせるにはどうすればよいですか?

4

2 に答える 2

2

2 つのリスナーを作成することでこれを解決しました。1 つはアプリの Documents ディレクトリにあり、新しいファイルが表示されるのを監視し、ファイル プロキシ オブジェクトは表示されるファイルごとに作成されます。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
于 2013-03-13T21:38:09.997 に答える
0

まず、次を参照してください。

簡単に言えば、これを行う優れた方法はないということです。理想的には、ファイルを別の場所に書き込んでから、ドキュメントに移動する必要があります。それはそれをアトミックアクションにします。または、特別なファイル名 (「.partial」、「.download」など) として書き込み、最後に名前を変更します (これも、2 番目の kqueue イベントを発生させるアトミック アクションです)。

于 2013-03-13T19:41:20.157 に答える