保护文档架构中的模型(Cocoa / Swift)

时间:2015-07-24 19:04:52

标签: swift cocoa nsdocument

我正在使用cocoa / swift编写基于OS X文档的应用程序。到目前为止,我有一个模型,由NSDocument子类管理。自定义视图由自定义视图控制器管理,后者更新视图以使它们与模型保持同步。

模型 - > controller->视图信息流非常明确。我让视图控制器观察文档,并且当文档更改时,视图控制器使用视图完成它们的工作。问题在于,在此过程中,模型的对象显然暴露给视图控制器,因此视图控制器也可以根据需要修改模型(或者如果我犯了错误)。

我希望该文档是唯一拥有修改模型对象“权限”的人。视图控制器应具有对它们的只读访问权限。有没有办法在Swift中做到这一点?

提前致谢。

1 个答案:

答案 0 :(得分:0)

在Swift中,private变量修饰符不适用于在同一文件中定义的类,因此如果将Model类定义放在与NSDocument子类相同的文件中,则NSDocument子类可以更改私有模型变量就像它们是公共的一样,但是在另一个文件中定义的NSViewController子类将无法访问私有模型变量。

然后,您可以通过编写以下内容使私有变量部分保密:

private(set) var name: String

...这将允许NSController子类读取它们,但不设置它们。 Swift为所有变量(不仅仅是计算属性)合成setter和getter,并告诉Swift将setter设为私有。

我用一些观察者代码测试private(set),上面的场景将允许NSDocument子类更改Model,但是如果NSViewController子类尝试更改Model,Xcode会立即标记带有错误的赋值: / p>

  

无法分配此表达式的结果

MyDocument.swift:

import Cocoa

class Employee: NSObject {
    private(set) var name: String

    init(name:  String) {
        self.name = name
        super.init()
    }
}


class MyDocument: NSDocument {

    dynamic var worker = Employee(name: "Joe")

    //...The rest of the NSDocument junk here
}

MyViewController.swift:

import Cocoa

class MyViewController: NSObject {


    var document: MyDocument
    var IdentifierForThisClass: Int = 0


    init(document: MyDocument) {

        self.document = document
        super.init()

        self.document.addObserver(self,
            forKeyPath: "worker",
            options: .Old | .New,
            context: &IdentifierForThisClass
        )
    }

    override func observeValueForKeyPath(
        keyPath: String,
        ofObject object: AnyObject,
        change: [NSObject : AnyObject],
        context: UnsafeMutablePointer<Void>) {

            println("Observer:")

            if context != &IdentifierForThisClass {
                println("This Observer message was meant for a parent class!")
                super.observeValueForKeyPath(keyPath,
                    ofObject: object,
                    change: change,
                    context: context
                )

                return
            }

            var newValue = change[NSKeyValueChangeNewKey] as! Employee

            println("\tThe worker has been changed to: \(newValue.name)")


    }

    func doStuff() {
        println("Inside doStuff():")
        println("\tThe worker's name is \(document.worker.name)")
        //document.worker.name = "Jenny"
    }

}

练习课程的一些代码:

let myDoc = MyDocument()

let viewController = MyViewController(
    document: myDoc
)

myDoc.worker = Employee(name: "Jenny")
viewController.doStuff()

--output:--
Observer:
    The worker has been changed to: Jenny
Inside doStuff():
    The worker's name is Jenny

然后,如果我取消注释该行:

doStuff() {
    ...
    //document.worker.name = "Jenny"
    ...
}

Xcode立即将其标记为错误。