【问题标题】:Overwriting NSDocument's init(contentsOf:ofType:) in Swift在 Swift 中覆盖 NSDocument 的 init(contentsOf:ofType:)
【发布时间】: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


    【解决方案1】:

    绝对是当前 swift 的一个缺点,据我所知,在 Swift 开发中讨论过。然而,超控可以很容易地实现。从 Apple 文档中可以清楚地看出,read(from:, typeName) 被调用,fileURLfileTypefileModificationDate 被设置。这是一些简单的调用,例如:

    convenience init(contentsOf url: URL, ofType typeName: String) throws {
        self.init()
        try self.read(from:url, ofType:typeName)
        self.fileURL = url
        self.fileType = typeName
        self.fileModificationDate = Date()
        //methods and sets values for the fileURL, fileType, and fileModificationDate properties.
        self.undoManager?.disableUndoRegistration()
        self.initializeGroups(false)
        self.managedObjectContext?.processPendingChanges()
        self.undoManager?.enableUndoRegistration()
    }
    

    我刚刚开始一个 NSPersistentDocument 子类,现在它运行良好。

    【讨论】:

    • 这种方法的问题是“覆盖”对 NSDocumentController 不可见。因此,必须按照 OP 描述的那样覆盖 NSDocumentController 的方法,并且基本上 OP 试图避免的事情。
    猜你喜欢
    • 2016-05-31
    • 2014-12-04
    • 2018-11-18
    • 2014-08-22
    • 2020-01-09
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多