如何从 Popover 调用主视图控制器的方法?

How to call from a Popover a method of the main view controller?

在一个 iOS 项目中,我有一个主要的 ViewController 和第二个 ViewController,第二个 ViewController 显示为带有按钮转场的弹出窗口在导航栏中。在那个弹出窗口中有一个带有此代码的按钮:

class Pop: UIViewController {

  @IBAction func colorOnePressed(_ sender: Any) {
        let vc = ViewController()
        vc. zoomIn()
    }

}

这是第一个视图控制器的方法:

class ViewController: UIViewController {

    @IBOutlet weak var mainTextField: UITextView!
    ...

    func zoomIn() {
        mainTextField.font = UIFont(name: "Helvetica Neue", size: CGFloat(18.00))
    }
}

不幸的是(显然对你们中的许多人来说)我得到了一个致命错误:"unexpectedly found nil while unwrapping an Optional value"。

您正在尝试从 ViewController 的新实例调用该方法。相反,您需要声明一个 delegate property in the Popover VC and pass the original parent VC within prepareForSegue:sender: 方法作为 Popover VC 的委托。

根据 and this answer by 对另一个问题的回答,我使用委托设计模式实现了这一点。如果它对某人有用,我 post 下面的代码。

注意:我通常看到您使用 UIPopoverPresentationControllerDelegate 协议,但我创建了一个自定义协议 (ZoomProtocol),因此我可以包含我的方法 (zoomOut())。

在主视图控制器中:

import UIKit

// declare a protocol, that lists variables and methods
// the delegate is expected to respond to
protocol ZoomProtocol {
    func zoomOut()
}

// set this view controller as the delegate
class ViewController: UIViewController, ZoomProtocol { 

    ...

    // make your presenting view controller conform to the protocol
    zoomOut() {
        // do something
    }

    // pass the this view controller as a delegate for the Popover view controller
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {        
        if let pop = segue.destination as? PopViewController {
            pop.delegate = self
        }
    }

}

在弹出视图控制器中:

import UIKit

class PopViewController: UIViewController {

    var delegate : ZoomProtocol?

    ...

    // when you want to, call the method on the presenting view controller
    @IBAction func zoomOutButtonPressed(_ sender: Any) {
        delegate?.zoomOut()
    }

}

在父视图控制器中,覆盖准备设置弹出窗口:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "yourPopoverIdentifier" {
        let popoverVC = segue.destination
        popoverVC.modalPresentationStyle = UIModalPresentationStyle.popover
        popoverVC.popoverPresentationController!.delegate = self
    }
}

然后在子视图控制器中,您只需调用 presentingViewController 即可访问父视图的功能。在这种情况下,父级是默认的视图控制器,ViewController.

@IBAction func buttonClick(_ sender: Any) {
    let parentVC = self.presentingViewController as! ViewController
    parentVC.functionOnParent()
}