5

我正在尝试监视本地和 iCloud 目录中的文件更改,并实现了 NSFilePresenter 协议方法,但唯一被调用的方法是presentedItemAtURL.

我是否正确假设我应该能够监视本地或 iCloud 目录并在任何进程添加、修改或删除目录中的文件时收到通知。

这是 OS X 应用程序的基本代码:

- (void)awakeFromNib {
        _presentedItemURL = myDocumentsDirectoryURL;
        _presentedItemOperationQueue = [[NSOperationQueue alloc] init];
        [_presentedItemOperationQueue setMaxConcurrentOperationCount: 1];
        _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
}
- (NSURL*) presentedItemURL {
    FLOG(@" called %@", _presentedItemURL);
    return _presentedItemURL;
}

- (NSOperationQueue*) presentedItemOperationQueue {
    FLOG(@" called");
    return _presentedItemOperationQueue;
}

- (void)presentedItemDidChange {
    FLOG(@" called");
    dispatch_async(dispatch_get_main_queue(), ^{
        [self reloadData];
    });
}
-(void)accommodatePresentedItemDeletionWithCompletionHandler:(void (^)(NSError *errorOrNil))completionHandler
{   FLOG(@" called");
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [self reloadData];
    }];
    completionHandler(nil);
}
-(void)presentedSubitemDidChangeAtURL:(NSURL *)url {
    FLOG(@" called");
    dispatch_async(dispatch_get_main_queue(), ^{
        [self reloadData];
    });
}
-(void)presentedSubitemDidAppearAtURL:(NSURL *)url {
    FLOG(@" called");
    dispatch_async(dispatch_get_main_queue(), ^{
        [self reloadData];
    });

}
4

3 回答 3

4

很久以前,我知道,但也许这仍然会有所帮助。NSFilePresenter 只会通知您另一个使用 NSFileCoordinator 对目录或文件进行更改的进程所做的更改。如果另一个进程(例如:iTunes 文件共享)在没有 NSFileCoordinator 的情况下进行了更改,您将不会收到通知。

于 2017-03-07T07:55:04.833 回答
0

这绝不是我的最终实现,我将在改进时进行编辑/更新。但是由于没有关于如何做到这一点的例子,我想我会分享一些有用的东西!!!没错,它有效。我能够在我的应用程序中读取该文件,同时在 textedit 中进行更改并将更改传播到我的应用程序。希望这有助于萌芽。

PBDocument.h

@interface PBDocument : NSObject <NSFilePresenter>

@property (nonatomic, strong) NSTextView *textView;

#pragma mark - NSFilePresenter properties
@property (readonly) NSURL *presentedItemURL;
@property (readonly) NSOperationQueue *presentedItemOperationQueue;

- (instancetype)initWithContentsOfURL:(NSURL *)url error:(NSError *__autoreleasing *)outError textView:(NSTextView*)textView;

@end

PBDocument.m

@interface PBDocument ()

@property (readwrite) NSURL *presentedItemURL;
@property (readwrite) NSOperationQueue *presentedItemOperationQueue;
@property (readwrite) NSFileCoordinator *fileCoordinator;

@end

@implementation PBDocument

- (instancetype)initWithContentsOfURL:(NSURL *)url error:(NSError *__autoreleasing *)outError textView:(NSTextView*)textView {
    self = [super init];
    if (self) {
        _textView = textView;
        _presentedItemURL = url;

        _presentedItemOperationQueue = [NSOperationQueue mainQueue];

        [NSFileCoordinator addFilePresenter:self];
        _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];

        [self readWithCoordination];
    }
    return self;
}

- (void)readWithCoordination {
    NSError *error = nil;

    [self.fileCoordinator coordinateReadingItemAtURL:_presentedItemURL options:NSFileCoordinatorReadingWithoutChanges error:&error byAccessor:^(NSURL *newURL) {
        NSLog(@"Coordinating Read");
        NSError *error = nil;
        NSFileWrapper *wrapper = [[NSFileWrapper alloc] initWithURL:newURL options:0 error:&error];

        if (!error) {
            [self readFromFileWrapper:wrapper ofType:[self.presentedItemURL pathExtension] error:&error];
        }

        if (error) @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"%@", error] userInfo:nil];
    }];

    if (error) @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:[NSString stringWithFormat:@"%@", error] userInfo:nil];
}

- (void)presentedItemDidChange {
    [self readWithCoordination];
}

@end
于 2014-03-18T02:34:53.243 回答
0

如果它对任何人有任何帮助,这就是FSEvents我最近最终用于文件同步解决方案的方法(),它似乎适用于任何文件系统。我最近没有对 NSFileCoordinator 进行任何研究,看看这是否更好或更糟,或者用例是什么作为比较。

我也没有测试每个用例,所以你的里程可能会有所不同。

https://github.com/eonil/FSEvents

于 2019-12-04T23:50:55.873 回答