保护文档架构中的模型(Cocoa/Swift)
Posted
技术标签:
【中文标题】保护文档架构中的模型(Cocoa/Swift)【英文标题】:Protecting the model in document architecture (Cocoa/Swift) 【发布时间】:2015-07-24 19:04:52 【问题描述】:我正在使用 cocoa/swift 编写一个基于 OS X 文档的应用程序。到目前为止,我有一个模型,由 NSDocument
子类管理。自定义视图由自定义视图控制器管理,它们更新视图以使它们与模型保持同步。
model->controller->view 的信息流很直接。我让视图控制器观察文档,当文档更改时,视图控制器会处理视图。问题是,在这个过程中,模型的对象显然暴露给视图控制器,因此如果我愿意(或者如果我犯了错误),视图控制器也可以修改模型。
我希望文档是唯一拥有“权限”修改模型对象的文档。视图控制器应该对它们具有只读访问权限。有没有办法在 Swift 中做到这一点?
提前致谢。
【问题讨论】:
注意:使用结构没有问题,因为在文档中将它们声明为private(set)
就可以了。对于类,虽然private(set)
只防止更改文档外部的引用,但不能更改对象的内容。
【参考方案1】:
在 Swift 中,private
变量修饰符不适用于在同一个文件中定义的类,因此如果将 Model 类定义与 NSDocument 子类放在同一个文件中,则 NSDocument 子类可以更改私有模型变量就像它们是公共的一样,但是在另一个文件中定义的 NSViewController 子类将无法访问私有模型变量。
然后您可以通过编写使私有变量部分私有:
private(set) var name: String
...这将允许 NSController 子类读取它们,但不能设置它们。 Swift 为所有变量(不仅仅是计算属性)合成 setter 和 getter,这告诉 Swift 将 setter 设为私有。
我用一些观察者代码测试了private(set)
,上面的场景将允许 NSDocument 子类更改 Model,但是如果 NSViewController 子类尝试更改 Model,Xcode 会立即将分配标记为错误:
不能赋值给这个表达式的结果
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 立即将其标记为错误。
【讨论】:
只有在与 NSDocument 相同的文件中定义模型对象时才有效,恐怕……以上是关于保护文档架构中的模型(Cocoa/Swift)的主要内容,如果未能解决你的问题,请参考以下文章