NSDocument 呈现的ItemDidChange 每秒调用一次

Posted

技术标签:

【中文标题】NSDocument 呈现的ItemDidChange 每秒调用一次【英文标题】:NSDocument presentedItemDidChange called every second 【发布时间】:2016-02-18 04:50:19 【问题描述】:

我正在研究NSDocument 子类。它表示文本编辑器中的文本文件。

我正在尝试使用 the NSFilePresenter protocol 来响应其他应用程序所做的更改(即,如果用户在 TextEdit 中保存更改,同时在此处打开同一个文件)。

我当前的实现是这样工作的……

我为文件协调器添加了一个属性:

@property (nonatomic) NSFileCoordinator *fileCoordinator;

我懒惰地创建它:

- (NSFileCoordinator *) fileCoordinator 
    if (!_fileCoordinator) 
        [NSFileCoordinator addFilePresenter:self];
        _fileCoordinator = [[NSFileCoordinator alloc] initWithFilePresenter:self];
    

    return _fileCoordinator;

presentedItemDidChange 被调用时,我从磁盘重新加载文件并显示它:

- (void)presentedItemDidChange 
    [super presentedItemDidChange];

    NSLog(@"presentedItemDidChange was called");

    if (self.presentedItemURL.isFileURL && self.fileType) 
        NSError *coordinatorError = nil;

        [self.fileCoordinator coordinateReadingItemAtURL:self.presentedItemURL options:NSFileCoordinatorReadingWithoutChanges error:&coordinatorError byAccessor:^(NSURL *newURL) 
            NSError *readError = nil;
            [self readFromURL:newURL ofType:self.fileType error:&readError];
            if (readError) NSLog(@"%@", readError);
        ];

        if (coordinatorError) NSLog(@"%@", coordinatorError);

        [self reloadString];
    

此代码有效:当我在 TextEdit 中保存文件时,更改会显示在我的应用程序中。

但是,一旦我保存了这个文件,presentedItemDidChange 就会被重复调用(大约每秒一次)。几分钟后,应用程序由于内存错误而崩溃。没有记录错误;控制台看起来基本上是这样的:

2016-02-17 22:43:46.233 MacDown[66847:2470964] presentedItemDidChange was called
2016-02-17 22:43:51.721 MacDown[66847:2470960] presentedItemDidChange was called
2016-02-17 22:43:52.816 MacDown[66847:2471206] presentedItemDidChange was called
2016-02-17 22:43:53.819 MacDown[66847:2470964] presentedItemDidChange was called
2016-02-17 22:43:54.920 MacDown[66847:2471206] presentedItemDidChange was called
2016-02-17 22:43:56.014 MacDown[66847:2470964] presentedItemDidChange was called
2016-02-17 22:43:57.115 MacDown[66847:2471206] presentedItemDidChange was called
2016-02-17 22:43:58.117 MacDown[66847:2470964] presentedItemDidChange was called

这是我第一次使用这些 API,所以我认为我犯了一个简单的错误。如果重要的话,我正在运行 OS X 10.11.3 和 Xcode 7.2。我做错了什么?

【问题讨论】:

【参考方案1】:

presentedItemDidChange 不仅会在文件内容更改时调用,还会在文件元数据更改时调用。 并且[NSDocument -readFromData:ofType:error:] 覆盖文件的最后打开日期,即文件元数据之一。

所以,这就是presentedItemDidChange 被反复调用的原因。如果要处理presentedItemDidChange 中的更新文件,通常需要首先确定更改的内容。

参见。 NSFilePresenter Protocol Reference

【讨论】:

【参考方案2】:

事实证明我不需要这些。 [NSDocument -readFromData:ofType:error:] 会在文件更改时自动调用,所以我只是在调用时使用新数据更新 UI。我错误地认为这个方法只在初始化期间被调用过一次。

(我仍然不确定为什么presentedItemDidChange 会被反复调用。)

【讨论】:

您是否设置了任何内容以调用readFromData:ofType:error:?我试图重现这一点,但只调用了presentedItemDidChange(我也委托给super)。但是,它被调用一次,而不是每秒调用一次。我怀疑这是导致这些变化的无关因素。

以上是关于NSDocument 呈现的ItemDidChange 每秒调用一次的主要内容,如果未能解决你的问题,请参考以下文章

从 NSDocument 获取 NSDocumentController

NSDocument 子类是不是是模型对象?

自动保存非来自用户的 NSDocument 模型更改

NSDocument - 内存泄漏和应用程序崩溃

当我不需要多文档支持时使用 NSDocument?

从 NSObject 获取 NSDocument