为什么我不能访问符合协议的destinationViewController的属性?

时间:2017-03-03 16:02:31

标签: swift segue protocols

我正在尝试将NSManagedObjectContext从一个视图控制器传递到我的prepareForSegue方法中的下一个视图控制器,但是我无法在destinationViewController中访问我为其创建的属性}:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
      switch identifier {
      case "segueToSettings", "pickLiftSegue":
        if let nav = segue.destinationViewController as? UINavigationController {
          let vc = nav.topViewController as! Dismissable
          vc.dismissalDelegate = self

          let context = viewModel.model.context
          vc.moc = context // <-- Value of type Dismissable has no member `moc`
        }
      case "segueToLog":
        let destinationVC = segue.destinationViewController as? Dismissable

        destinationVC?.dismissalDelegate = self
      default:
        break
      }
    }
  }

这是destinationViewController的相关部分:

class SettingsViewController: UITableViewController, Dismissable, DismissalDelegateProtocol {

    @IBOutlet weak var forumlasTitle: UILabel!
    @IBOutlet weak var liftsTitle: UILabel!
    @IBOutlet weak var weightUnitControl: UISegmentedControl!
    @IBOutlet weak var roundNumbersSwitch: UISwitch!
    @IBOutlet weak var currentFormulaSelection: UITableViewCell!
    @IBOutlet weak var currentLiftsSelection: UITableViewCell!

    var dismissalDelegate: DismissalDelegateProtocol?
    var moc: NSManagedObjectContext? = nil // <-- There it is right there
}

我在vc.mocprepareForSegue收到了您在上面看到的错误,这明显说明符合Dismassable协议的视图控制器没有名为moc的属性,这是真的:

protocol Dismissable: class {
    weak var dismissalDelegate: DismissalDelegateProtocol? { get set }
    }

但是我不应该在不将其作为协议的一部分的情况下访问视图控制器本身的属性吗?

我已经搜索了很长一段时间并梳理了Apple's Protocol documentation,但我还没有找到答案。我以为我对协议有了很好的处理,但似乎我仍然缺少一两个关键概念。

1 个答案:

答案 0 :(得分:1)

问题是编译器只知道你告诉它的内容。你说:

let vc = nav.topViewController as! Dismissable

现在vc是一个Dismissable,它是编译器知道的 all 。并且Dismissable没有moc属性。因此,当您尝试讨论Dismissable的moc属性时,编译器会阻止您进入。

但是一个SettingsViewController 确实具有moc属性,正如你自己指出的那样。所以告诉编译器这个一个SettingsViewController,如果是这样的话:

if let svc = vc as? SettingsViewController {
    svc.moc = context
}

但想想更多。由于SettingsViewController 是一个Dismissable,,并且编译器知道这个,实际上是你需要的强制转换,因为现在你也可以访问不允许的财产。因此,您的代码可以完全重写:

    if let nav = segue.destinationViewController as? UINavigationController {
      if let vc = nav.topViewController as? SettingsViewController {
        vc.dismissalDelegate = self // fine, because a SVC is a Dismissable
        let context = viewModel.model.context
        vc.moc = context // fine, because a SVC is a SVC :)
      } 
    }

换句话说,以这种方式看待它:编译器知道SettingsViewController是一个Dismissable。但没有法律规定每个Dismissable都是一个SettingsViewController。你的原始代码有向后的关系,就是这样。