在Swift

时间:2016-08-12 02:24:25

标签: swift cocoa nsdocument

背景:

关于基于文档的Cocoa应用程序,Apple建议覆盖NSDocument的init(contentsOf:ofType:)以自定义内容,因此它似乎是一个优先覆盖的地方。

  

您可以覆盖此方法以自定义重新打开自动保存的文档。

     

比照init(contentsOf:ofType:) - NSDocument | Apple Developer Documentation

但是在Swift上,实际上这是不可能的,因为在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:)更模糊超级行为是非常复杂和模糊的。 (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
}

1 个答案:

答案 0 :(得分:0)

肯定是当前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子类,现在效果很好。