我正在使用cocoa / swift编写基于OS X文档的应用程序。到目前为止,我有一个模型,由NSDocument
子类管理。自定义视图由自定义视图控制器管理,后者更新视图以使它们与模型保持同步。
模型 - > controller->视图信息流非常明确。我让视图控制器观察文档,并且当文档更改时,视图控制器使用视图完成它们的工作。问题在于,在此过程中,模型的对象显然暴露给视图控制器,因此视图控制器也可以根据需要修改模型(或者如果我犯了错误)。
我希望该文档是唯一拥有修改模型对象“权限”的人。视图控制器应具有对它们的只读访问权限。有没有办法在Swift中做到这一点?
提前致谢。
答案 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立即将其标记为错误。