【问题标题】:UIViewControllers sharing 'generic' IBActionUIViewControllers 共享“通用”IBAction
【发布时间】:2019-01-03 09:59:30
【问题描述】:

我有一个带有 6 个UIViewControllers 的应用程序。

任何viewcontroller 都具有这样的功能:

@IBAction func onHelp(_ sender: UIBarButtonItem) {

        DispatchQueue.main.async(execute: { () -> Void in
            let helpVC =  self.storyboard?.instantiateViewController(withIdentifier: "Help") as! HelpViewController
            helpVC.starter = "MapHelp"
            helpVC.helpSubtitle = "Map"
            self.present(helpVC, animated: true, completion: nil)
        })

    }

任何viewcontroller 中的任何IBAction 都呈现相同的HelpViewController,但传递不同的参数(starterhelpSubtitle)。

由于我不喜欢重复代码,首先我认为应该将这个函数转换为更通用的东西。

但是:有没有办法创建一个通用的IBAction,适用于每个viewcontroller

【问题讨论】:

  • UIBarButtonItem,这不是 NavigationController 按钮吗?将 NavigationController 子类化,添加该方法,然后在每个 ViewController 上添加协议扩展来检索参数怎么样?
  • 为什么不创建一个 BaseViewController,让你的所有 ViewController 都继承自那个,在每个 VC 中创建 IBAction,从所有子类调用相同的父类方法。这样代码就可以重用,你不必到处都写代码,也不必担心创建一个通用的 IBAction。使方法通用,保持 IBActions 分开。您也可以在基类方法的签名中提供参数,这可能因 VC 而异
  • 还有什么理由你专门在主线程中这样做? IBActions 默认在主线程上执行。
  • @Larme :是的,它是一个导航控制器,但是,请你扩展一下吗?我不确定我是否理解您的解决方案。
  • 我已经删除了我的答案。它不会真正起作用,因为协议方法不能是@IBAction

标签: swift function viewcontroller dry ibaction


【解决方案1】:

创建一个 BaseViewController 并在其中添加通用方法。

class BaseViewController: UIViewController {



override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    func genericMethod(starter: String, helpSubtitle: String){
        let helpVC =  self.storyboard?.instantiateViewController(withIdentifier: "Help") as! HelpViewController
        helpVC.starter = starter
        helpVC.helpSubtitle = helpSubtitle
        self.present(helpVC, animated: true, completion: nil)
    }

    @IBAction func onHelp(_ sender: UIButton?) {
       //You can use this method as generic IBaction if you want. It can be connected to buttons of all child View Controllers. But doing so will limit your param sending ability. On the plus side though, you won't have to define an IBAction everywhere and you can simply connect your child VC's button to Parent Class' IBAction.
    }

}

现在从这个类继承你的 ViewControllers,比如:

import UIKit

class ViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func btnTapped(_ sender: Any) {
        genericMethod(starter: "View Controller", helpSubtitle: "I was triggered from VC1")
    }

}

import UIKit

class SecondViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    @IBAction func btnTapped(_ sender: Any) {
        genericMethod(starter: "View Controller 2", helpSubtitle: "I was triggered from VC2")
    }

}

就是这样。您的两个 ViewController 都可以调用父方法。如果您仍想使用通用 IBAction,您也可以这样做,但我不建议您使用该课程,因为您想传递可以变化的参数。如果你想这样做,它看起来像这样:

请记住,这里的 ViewController 是从基础 ViewController 继承的,这就是它可以访问父类中定义的 IBActions 的原因。您所要做的就是拖动和连接。

【讨论】:

  • 我喜欢它,但是,即使在研究之后,我也希望可以做一些事情来拥有一种通用的 IBAction。谢谢:-)
  • IBAction 与“泛型”或“泛型方法”无关,它仍然是一个函数,只是在 IB 中可见。
  • @Injectios 不确定是什么给人的印象是我在暗示其他情况。如果有帮助,英语是我的第二语言,所以我可能不够清楚。我所说的泛型是指可以被多个对象使用的单一方法。
  • 所以这些对象在 IB 中必须是相同的类型/类。否则,如果您声明了不同的类型/类,那么您的函数将不可见,您可以尝试使用协议/或继承,并使您的所有视图控制器符合声明 IBAction 的协议,但从未尝试过。
  • @Injectios 如果所有这些对象都继承自同一个父类,那么是的,它可以工作。其他类型将无法访问它,但话又说回来,在 OP 的场景中,他们不必这样做。只有 VC 需要访问它。那么重点是什么?至于您的其他建议,OP 必须在所有 VC 中为协议的方法签名提供定义,这正是他们想要避免的。您可以通过创建 UIViewController 的扩展来尝试 Sulthan 采用的路线,但正如他所说,协议方法不能是 IBActions。
猜你喜欢
  • 1970-01-01
  • 2012-05-19
  • 2016-07-29
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多