使用委托

时间:2018-03-15 22:29:58

标签: ios swift

我有ViewController调用自定义类PopOverModal并传入自己和子ViewController。

class ViewController: UIViewController {
   ...
    @IBAction func testPopOver(_ sender: Any) {
       var childVC = // initialize child view controller with view from storyboard
       var myPopOverModal = PopOverModal(parent: self, child: childVC);
    }
   ...
}

我需要childVC将一些任务委托给PopOverModal。

class ChildViewController: UIViewController {
    ...
    weak var delegate: PopOverModal?
    ...
}

class PopOverModal {
    init(parent: UIViewController, child: UIViewController) {        
        child.delegate = self
        child.dismiss(animated: true, completion: nil)
    }
}

PopOverModal的初始化程序会出错,因为UIViewController没有属性delegate

然后我做了以下事情:

protocol PopOverViewController: class {
    weak var delegate: PopOverModal? {get set}
}

class ChildViewController: UIViewController, PopOverViewController {
    ...
    weak var delegate: PopOverModal?
    ...
}

class PopOverModal {
    init(parent: UIViewController, child: PopOverViewController) {        
        child.delegate = self
        child.dismiss(animated: true, completion: nil)
    }
}

但是,现在我收到dismiss不是PopOverViewController函数的错误。

如果确保ChildViewController继承自UIViewController,我能做些什么才能访问UIViewController和PopOverViewController的函数和属性?

我知道我可以创建一个继承自UIViewController并符合PopOverViewController的Hybrid类,让我的ChildViewController继承它,但还有另一种方法吗?

1 个答案:

答案 0 :(得分:1)

如果保证child将是ChildViewController类的实例,那么您可以修改初始化程序签名,以便它接受相应的对象:

init(parent: UIViewController, child: ChildViewController) {        
  child.delegate = self
  child.dismiss(animated: true, completion: nil)
}

如果它可以是任意UIViewController,但delegate仅适用于ChildViewController的实例,那么您可以使用带有可选链接或可选绑定的类型转换:

// Option #1 - optional chaining
init(parent: UIViewController, child: UIViewController) {
  (child as? ChildViewController)?.delegate = self
  child.dismiss(animated: true, completion: nil)
}

// Option #2 - optional binding
init(parent: UIViewController, child: UIViewController) {
  if let child = child as? ChildViewController {
     child.delegate = self
  }
  child.dismiss(animated: true, completion: nil)
}

顺便说一下,使用基于协议的委派被认为是最佳实践。以下是如何完成的示例:

protocol PopOverDelegate: class {
  // add any methods and properties that the delegate should implement
  func didPressButton()
}

class ChildViewController: UIViewController {
  ...
  weak var delegate: PopOverDelegate?
  ...
  // call delegate methods where you need them
  func onButtonPress() {
    self.delegate?.didPressButton()
  }
}

class PopOverModal: PopOverDelegate {
  init(parent: UIViewController, child: UIViewController) {        
    (child as? ChildViewController)?.delegate = self
    child.dismiss(animated: true, completion: nil)
  }

  // MARK: - delegate methods
  func didPressButton() {
    print(#function)
  }
}