首页 文章

Swift4,如何通过在当前视图控制器的子视图中以编程方式创建的单击按钮呈现另一个视图控制器

提问于
浏览
1

我在UIStackView中以编程方式创建了一些UIButtons . StackView是原始视图控制器的子视图 .

如何通过单击按钮呈现另一个视图控制器?

我试过控制拖动来创建从原始控制器到目标控制器的segue并尝试使用 self.performSegue(withIdentifier: "showMealTable", sender: self) 进行导航 .

但它在运行时抛出错误 "..has no segue with identifier 'showMealTable''" .

这是我的StackView类

@IBDesignable class TimeLineHeadControl: UIStackView {
   //MARK: Properties
   private let timeLineControllerInstance = TimeLineController()
   ....
   button.addTarget(self.timeLineControllerInstance, action: #selector(TimeLineController.breakfastButtonTapped(button:)), for: .touchUpInside)
   ....
}

和我原来的视图控制器

class TimeLineController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //self.performSegue(withIdentifier: "showMealTable", sender: self)
    }

    ...

    @objc func breakfastButtonTapped(button: UIButton) {
        print("at Time Line Controller")
        self.performSegue(withIdentifier: "showMealTable", sender: self)
    }
    ...

}

Created segue

error message here

3 回答

  • 0

    根据定义,segue不能独立于故事板而存在 . 即使你看到了 class 的名字:UIStoryboardSegue . 您不能以编程方式创建segue,但您可以做的是在storyboard中设置segue,然后在该按钮上设置一个函数并使用该函数执行操作 .

    而且,您甚至可以在不使用segue的情况下实现此目的 . 您可以在公共视图控制器(基类)中创建一个将转换为新视图控制器的方法 . 在您的情况下,基类可以是MealViewController,新的视图控制器可以是MealTableViewController .

    - (IBAction)pushNewViewController
    {
        NewViewController *newVC = [[NewViewController alloc] init];
    
        // do any setup you need for newVC like passing data.
    
        [self presentModalViewController:newVC animated:YES];
    }
    

    现在,您可以在单击相应按钮时调用此方法 .

  • 1

    我们先来谈谈错误的原因 .

    这里:

    private let timeLineControllerInstance = TimeLineController()
    

    使用上述行创建的此VC与您在应用中看到的VC不同 . 这是 TimeLineController 的另一个全新实例,未通过故事板初始化 . 因此,它没有segue .

    您需要实际设置当前显示为 timeLineControllerInstance 的VC .

    However ,不管怎样,你违反了MVC原则 . TimeLineHeadControl 是一个视图 . 视图不应该依赖于控制器 . 视图可以发送消息(目标操作/代理),控制器可以选择监听这些消息 . 控制器选择要控制的视图,而不是相反 .

    你应该在视图控制器中调用 addTarget

    // in viewDidLoad
    yourStackView.button.addTarget(self, action: #selector(breakfastButtonTapped(button:)), for: .touchUpInside)
    

    或创建 TimeLineHeadControlDelegate 并使用委托模式 .

  • 0

    你可以通过使用代码来做到这一点......

    @objc func breakfastButtonTapped(button: UIButton) {
            print("at Time Line Controller")
                let vc = self.storyBoard.instantiateViewController(withIdentifier: "yourVCidentifier") as! YourVC
            self.present(vc,animated: true, completion: nil)
        }
    

    如果你想用segue做到这一点..给你的segue提供storyBoard segue标识符,而不是调用执行segue .

相关问题