从另一个视图控制器调用视图控制器中的函数

时间:2016-10-29 19:31:57

标签: swift view controllers

以下是建议委托流程的代码......

在主视图控制器中......

protocol FilterDelegate: class {
    func onRedFilter()
    func onGreenFilter()
    func onBlueFilter()
    func onUnfiltered()
}

class ViewController: UIViewController, FilterDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

----

// Increase red color level on image by one.
    func onRedFilter() {

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if segue.identifier == "filterSegue" {

            let dest = segue.destinationViewController as!    CollectionViewController
            dest.filterDelegate = self

        }
    }
集合视图控制器中的

......

var filterDelegate: FilterDelegate?
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    print("Cell \(indexPath.row) selected")

    guard let filterDelegate = filterDelegate else {
        print("Filter delegate wasn't set!")
        return
        }

    switch indexPath.row {

        case 0:
            filterDelegate.onRedFilter()
        case 1:
            filterDelegate.onGreenFilter()
        case 2:
            filterDelegate.onBlueFilter()
        case 3:
            filterDelegate.onUnfiltered()
        default:
            print("No available filter.")

    }

现在......代码在保护块处停止并打印错误消息。任何按下单元格都不会执行开关块。

1 个答案:

答案 0 :(得分:0)

您在倒数第二句中的理论是正确的 - 当您在“子”视图控制器中调用storyboard.instantiateViewControllerWithIdentifier时,您实际上是在创建一个全新的主视图控制器实例。您获取对现有主视图控制器的引用,这就是您调用的方法没有任何效果的原因。

有几种方法可以实现您的目标,包括delegate pattern或使用闭包。以下是使用委托协议的概述:

protocol FilterDelegate: class {
    func onRedFilter()
    func onGreenFilter()
    func onBlueFilter()
    func onUnfiltered()
}

class MainViewController: UIViewController, FilterDelegate {

    // implement these as required
    func onRedFilter() { }
    func onGreenFilter() { }
    func onBlueFilter() { }
    func onUnfiltered() { }

    // when we segue to the child view controller, we need to give it a reference
    // to the *existing* main view controller
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let dest = segue.destination as? ChildViewController {
            dest.filterDelegate = self
        }
    }

}

class ChildViewController: UIViewController {

    var filterDelegate: FilterDelegate?

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

        // ... 

        guard let filterDelegate = filterDelegate else {
            print("Filter delegate wasn't set!")
            return
        }

        switch indexPath.row {
            case 0:
                filterDelegate.onRedFilter()
            case 1:
                filterDelegate.onGreenFilter()
            case 2:
                filterDelegate.onBlueFilter()
            case 3:
                filterDelegate.onUnfiltered()
            default:
                print("No available filter.")

        }

    }

}

另一种选择是在ChildViewController上为孩子需要调用的MainViewController上的每个函数提供闭包,并在prepareForSegue中设置它们。使用委托看起来有点干净,因为在这种情况下有很多函数。