Objective c NSFileHandleDataAvailableNotification仅发送一次

Objective c NSFileHandleDataAvailableNotification仅发送一次,objective-c,cocoa,Objective C,Cocoa,在我的应用程序中,我设置了一个NSFileHandle,以便在文件更新时(尝试)读取文件。但是,第一次修改文件时,我只收到一个通知。waitForDataInBackgroundAndNotify是从NSApplication的子类调用的,因此存在一个活动的runloop。我认为唯一可能影响这一点的问题是,编写文件的过程使用NSDictionarywriteToFile和原子性:true。这是个问题吗? 我还缺什么吗 FWIW,我可以用runloop中的计时器替换通知,并以这种方式读取文件。有点

在我的应用程序中,我设置了一个
NSFileHandle
,以便在文件更新时(尝试)读取文件。但是,第一次修改文件时,我只收到一个通知。
waitForDataInBackgroundAndNotify
是从
NSApplication
的子类调用的,因此存在一个活动的runloop。我认为唯一可能影响这一点的问题是,编写文件的过程使用
NSDictionary
writeToFile
原子性:true
。这是个问题吗?
我还缺什么吗

FWIW,我可以用runloop中的计时器替换通知,并以这种方式读取文件。有点违背了回调的目的

设置文件句柄

- (void)setupRead:(id)sender
{
    self.fileHandle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/some/file.xml"];
    if( self.fileHandle == nil )
    {
        [self.taskLabel setStringValue:@"Error:"];
        [self.taskText setStringValue:@"Unable to connect to status file"];
        return;
    }

    // register for notifications
    [self.fileHandle waitForDataInBackgroundAndNotify];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(readData:) name:NSFileHandleDataAvailableNotification object:nil];
}
读取回调

- (void)readData:(NSNotification*)note
{
    NSData* msg = [self.fileHandle availableData];
    if( [msg length] )
    {
        NSError* error = nil;
        NSDictionary* statusDictionary = [NSPropertyListSerialization propertyListWithData:msg options:NSPropertyListImmutable format:nil error:&error];
        [self displayStatus:statusDictionary];
    }    
    [self.fileHandle waitForDataInBackgroundAndNotify];
}

你试过非原子化写作吗?我过去也做过类似的事情,这就是问题所在。即使写入不是原子的(原子=写入tmp,然后替换文件,非原子=截断并写入),
availableData
读取到文件末尾,所以不需要文件句柄保持打开状态。如果外部进程将进行非原子写入,fh的读取位置(也称为seek)无论如何都不是零,因此您不能在不倒带的情况下“重新读取”。不幸的是,我无法控制写入程序,因此更改为非原子写入最多也会有问题。我确实尝试添加seekToFileOffset,但每次读取都收到相同的数据。也就是说,我收到了NSFileHandleDataAvailableNotification,但数据始终与初始数据相同。有趣。我似乎在从“旧”文件获取数据时收到了来自“新”文件的通知。