【发布时间】:2016-08-12 02:24:25
【问题描述】:
背景:
关于基于文档的 Cocoa 应用程序,Apple 建议重写 NSDocument 的 init(contentsOf:ofType:) 来自定义内容,因此它似乎是一个重写的好地方。
您可以重写此方法来自定义重新打开自动保存的文档。
参见。 init(contentsOf:ofType:) - NSDocument | Apple Developer Documentation
但是在 Swift 上,这实际上是不可能的,因为 super 的 init(contentsOf:ofType:) 不能在 init(contentsOf:ofType:) 中调用,因为这个初始化程序是便利初始化程序之一。
convenience init(contentsOf url: URL, ofType typeName: String) throws {
try super.init(contentsOf: url, ofType: typeName) // <- this marked as error
}
我想要什么:
当我在Objective-C中编写基于文档的应用程序时,我使用这种方法,即initWithContentsOfURL:ofType:error:,仅为使用现有文件打开的文档准备一些与文件相关的属性,而不是为新的空白文档或恢复文件。
它不能简单地用 NSDocument 的 read(from:ofType) 代替,因为它不仅会在文档打开时被调用,而且在每次重新加载文档时都会被调用(例如 Revert)。
我也无法在正常的init() 上做我的事情,因为此时尚未设置fileURL 属性。
init() {
super.init()
self.fileURL // <- returns nil
}
我知道便利构造器必须调用指定构造器,但 init(contentsOf:ofType:) 与 init(type:) 不同,模仿 super 的行为非常复杂且不清楚。 (How do I initialise a new NSDocument instance in Swift?)
这样的? (但不确定)
convenience init(contentsOf url: URL, ofType typeName: String) throws {
self.init()
self.fileURL = url
self.fileType = typeName
self.fileModificationDate = (try? FileManager.default.attributesOfItem(atPath: url.path))?[.modificationDate] as? Date
}
问题:
所以,我的问题是:在打开文档时只使用一次 fileURL 的合适点在哪里?
解决方法 1:
对于解决方法,我目前覆盖 NSDocumentController 子类的 makeDocument(withContentsOf:ofType:,并从调用 self.init(contentsOf: url, ofType: typeName) 的原始文档的初始化程序创建一个文档。
解决方法 2:
我上面提到的第一个解决方法并不安全。我发现最好在单独的函数中进行额外的初始化。
override func makeDocument(withContentsOf url: URL, ofType typeName: String) throws -> NSDocument {
let document = try super.makeDocument(withContentsOf: url, ofType: typeName)
(document as? Document)?.additionalInit() // call original func
return document
}
【问题讨论】:
标签: swift cocoa nsdocument