一周前,我开始用Swift学习OS X编程。我决定首先创建一个简单的双面板文件管理器来学习语言基础知识和API。但现在我发现了一些奇怪的行为,我既不理解也不能在文档中找到解释。让他通过例子来解释。
我有一个自定义的ViewController类SplitViewController,它表示文件管理器窗口的主要双面板部分。为了让它与底层的View控制器通信,我还使用FileManagementDelegate协议扩展它,它定义了一些有用的方法。
我还有一个OnePanelViewController类,用于管理每个文件面板。它还通过协议扩展,此时FilePanelController一个,再次用于控制器间通信需求。该协议定义为:
protocol FilePanelController {
var delegate: FileManagementDelegate? {get set}
var ID: Int? {get set}
func getSelectedFiles() -> [NSURL]
func getFocus() -> Bool
func gotFocus()
}
在SplitViewController类的viewDidAppear()方法中,我需要将运行实例设置为两个文件面板的委托。我试着这样做:
for controller in self.childViewControllers{
if controller is FilePanelController {
(controller as! FilePanelController).delegate = self
}
}
但这会导致编译时错误:“无法分配给'FileManagementDelegate'类型的不可变表达式?'”
我尝试将代码更改为:
for var controller in self.childViewControllers{...
但它也没有用。
同时如果我将其更改为:
for controller in self.childViewControllers{
if controller is FilePanelController {
(controller as! OnePanelViewController).delegate = self
}
}
然后一切正常。
要访问委托属性作为FilePanelController协议的属性而不是OnePanelViewController类的属性,我必须这样做:
for controller in self.childViewControllers{
if controller is FilePanelController {
var fpController: FilePanelController = (controller as! FilePanelController)
fpController.delegate = self
}
}
看起来有点尴尬。
我不明白为什么?它是同一类的相同属性。我看不出有什么问题?
答案 0 :(得分:1)
Swift中的协议可以应用于类和结构。编制者不知道你在使用哪个,所以他限制它。
您可以将协议定义为仅适用于类:
protocol FilePanelController: class { ... }
或使用条件转换:
for controller in self. childViewControllers {
if var filePanelViewController = controller as? FilePanelController {
filetPanelViewController.delegate = self
}
}
当您使用OnePanelViewController
作为强制类型时,编译器推断它是类。