我的应用在OS X上使用NSPersistentDocument
(没有自动保存),在iOS上使用UIDocument
(也没有自动保存)。文件表示是二进制核心存储。自iOS 7 + macOS 10.10以来,此应用程序一直运行良好。
如果我在OS X 10.13上打开文档,而另一台设备(macOS 10.13或iOS 11)打开同一个文件,则在下次保存时我会收到警告"此文档的文件自打开或保存后,其他应用程序已更改。" 。该警告是虚假的,因为在另一台设备上只发生了打开 - 而不是保存。
在查找此通知的可能原因时,我注意到当一台设备上发生iCloud文件打开时,会更新名为com.apple.lastuseddate#PS
的扩展属性。我已经确认这个扩展属性在iOS 11和macOS 10.13上都已更新。此扩展属性似乎未在iOS或macOS的早期版本中使用。我想知道文件元数据的更新是否会触发这种虚假警告。
(我怀疑这个属性可能与iOS 11上的NSFileProvider
有关,因为在[...}}上有一个新方法setLastUsedDate:forItemIdentifier:completionHandler:
和FinderSync
,因为setLastUsedDate:forItemWithURL:completion:
也是新。)
我的问题是 - 其他人是否看到了这种新行为?是否会引起其他人如此恼人的副作用?
答案 0 :(得分:0)
我进一步研究了这个问题。我已经确定了似乎正在发生的事情,还有解决方法。请注意,这仅适用于NSPersistentDocument
- 没有自动保存。
首先是关于文件时间戳和文件系统类型的重要说明。 HFS+
个时间戳的分辨率为一秒。 APFS
timestamps have a resolution of 1 nanosecond
当OS X App的iCloud容器迁移到APFS
时,我的问题才开始显现。
这是一个典型的序列(我使用OS X和iOS作为示例设备 - 但无论操作系统类型如何,对于其他' iCloud连接设备都会发生相同的序列:
APFS
上的文件修改日期将包含小数第二个组件。presentedItemDidChange
在此处调用时间)。 NSDocument
self.fileModificationDate
(包含小数秒组件)与文件修改日期(已截断小数秒组件)之间不匹配。其含义是:
我使用的解决方法(只是因为我使用的NSPersistentDocument
不支持自动保存才有必要)是将self.fileModificationDate
设置为小数秒截断版本(是的,它被读取) -write),当且仅当 self.fileModificationDate
匹配文件修改日期而忽略小数秒。如果这样做,则警告不会出现 - 并且不会造成任何损害(因为文件未被修改):
// saving file changes
NSDate *modDate = nil;
[self.fileURL getResourceValue:&modDate forKey:NSURLContentModificationDateKey error:NULL];
if (modDate && self.fileModificationDate) {
NSTimeInterval delta = [modDate timeIntervalSinceDate:self.fileModificationDate];
if (fabs(delta) > 0.0 && [modDate ss_isEqualToDateInSeconds:self.fileModificationDate])
self.fileModificationDate = modDate.ss_dateWithDateInSeconds;
}
[self saveDocumentWithDelegate:self
didSaveSelector:@selector(documentSaved:didSave:contextInfo:)
contextInfo:nil];
正如我在一开始所说的那样 - 令人惊讶的行为。如果记录下来会很好。因为我使用NSDocument
是非标准的,所以我不知道其他人是否有这个问题。