通过单击表格视图单元格中的不同元素打开不同的新视图控制器 - Swift 3

时间:2016-12-17 05:25:54

标签: uitableview uiviewcontroller swift3 xcode8

我的表格视图单元格显示具有两个不同按钮元素的实体。我希望能够启动一个视图控制器,如果我点击第一个按钮,则会显示一系列食物项目,而另一个视图控制器会在我点击第二个按钮时显示一系列饮料。

我能够正确地将数据传递给新的视图控制器,但似乎无法关闭当前视图并加载新视图。我的代码是这样的:

在表格视图单元格

    @IBAction func foodBtnPressed(_ sender: Any) {
    print("foodBtn pressed")
    print("customer is \(customer?.name)")
    vc.loadChooserScreen(toChoose: "Food", forCustomer: customer!)
}

@IBAction func beverageBtnPressed(_ sender: UIButton) {
    print("beverageBtn pressed")
    print("customer is \(customer?.name)")
    vc.loadChooserScreen(toChoose: "Beverage", forCustomer: customer!)
}

在表格视图控制器

    func loadChooserScreen(toChoose: String, forCustomer: Customer) {
    print("Choose \(toChoose)")
    print("For \(forCustomer.name)")

    if toChoose == "Food" {
        let foodVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "foodMenu") as? FoodVC
            foodVC?.loadCustomerToEdit(customer: forCustomer)
            dismissVC(sender: Any.self)
     }

    else if toChoose == "Beverage" {
        let beverageVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "beverageMenu") as? BeverageVC
        beverageVC?.loadCustomerToEdit(customer: forCustomer)
        dismissVC(sender: Any.self)
    }

    else {
        // do nothing
    }

}
    func dismissVC(sender: Any) {
    print("Reached dismissVC function in selectionMenu")
    dismiss(animated: true, completion: {
    self.delegate!.dismissViewController()
    })
}

在此视图控制器中,我还有以下协议

protocol OrderVCProtocol {
func dismissViewController()
}

并定义了

var delegate: OrderVCProtocol!

在我的根视图控制器

    func dismissViewController() {
    print("Reached dismissViewController function in rootView")
    if let foodVC = self.storyboard?.instantiateViewController(withIdentifier: "foodMenu") {
        self.present(foodVC, animated: true, completion: nil)
    }

    if let beverageVC = self.storyboard?.instantiateViewController(withIdentifier: "beverageMenu") {
        self.present(beverageVC, animated: true, completion: nil)
    }
}

在此处调用表视图控制器时设置委托

    @IBAction func loadOrderView(_ sender: Any) {
    let orderVC = self.storyboard?.instantiateViewController(withIdentifier: "orderView") as! OrderVC
    orderVC.delegate = self
    self.present(orderVC, animated: true, completion: nil)
}

在我的目标视图控制器中,我有以下功能

func loadCustomerToEdit(customer: Customer) {
    self.customerToEdit = customer
    print("IN FoodVC THE CUSTOMER TO EDIT IS \(self.customerToEdit.name)")
}

和BeverageVC中相应的一个。

当我运行应用程序时,不会抛出任何错误,我从打印语句中获得控制台中的以下示例输出:

  

foodBtn紧迫

     

客户是可选的(“John”)

     

选择食物

     

For Optional(“John”)

     

IN FoodVC编辑的客户是可选的(“John”)

     

在selectionMenu

中达到了dismissVC功能

以及点击饮料按钮时的相应响应。

然后没有任何反应。所以我知道数据正确传递给新的视图控制器,但我不知道如何关闭当前屏幕并显示带有选择的新屏幕。

我希望我的问题足够明确?我不确定是什么问题,但控制台输出清楚地表明代码运行正常,直到它试图解除当前视图。

编辑添加:

如果我在tableview控制器中修改我的dismissVC函数,如下所示:

func dismissVC(sender: Any) {
print("Reached dismissVC function in selectionMenu")
delegate.dismissViewController()
}

控制台视图现在抛出

  

致命错误:在解包可选值时意外发现nil

如果我再次将其修改为以下内容,它会回到没有错误并且卡在同一个地方(即打印行“Stuck where delegate dismisses view”),表明代表仍然是nil ..但是为什么当我在根视图中设置并在此视图中加载它时,它是否为零?

func dismissVC(sender: Any) {
print("Reached dismissVC function in selectionMenu")
if delegate != nil {
    delegate?.dismissViewController()
    } else {
print("Stuck where delegate dismisses view")
}

1 个答案:

答案 0 :(得分:0)

我通过通知中心和代表实施通知解决了我的问题。首先,在我的AppDelegate文件中,我在底部添加了这一行

let notifyCnt = NotificationCenter.default

接下来,我将tableview单元格函数修改为

@IBAction func foodBtnPressed(_ sender: Any) {
notifyCnt.post(name: NSNotification.Name(rawValue: "toChoose"), object: nil, userInfo: ["toChoose": "Food", "forCustomer": customer])
}

@IBAction func beverageBtnPressed(_ sender: UIButton) {
    notifyCnt.post(name: NSNotification.Name(rawValue: "toChoose"), object: nil, userInfo: ["toChoose": "Beverage", "forCustomer": customer])
}

然后,在tableview控制器中我将其修改为:

protocol ChooserViewDelegate: class {
func loadChooserView(choice: String, forCustomer: Customer)
}

并定义了

weak var delegate: ChooserViewDelegate?

并在我的ViewDidLoad部分

中添加了此内容
notifyCnt.addObserver(forName: Notification.Name(rawValue: "toChoose"), object: nil, queue: nil, using: loadChooserScreen)

最后修改了我的选择器功能:

func loadChooserScreen(notification: Notification) {

    guard let userInfo = notification.userInfo,
        let toChoose = userInfo["toChoose"] as? String,
        let planToEdit = userInfo["customer"] as? Customer else {
            print("No userInfo found in notification")
            return
    }
    delegate?.loadChooserView(choice: toChoose, forCustomer: customer)
}

然后在我的根视图控制器中,我有以下内容来替换我之前的内容:

/*Conform to ChooserViewDelegate Protocol */
func loadChooserView(choice: String, forCustomer: Customer) {
  self.customer = forCustomer
  dismiss(animated: false, completion: {
    if choice == "Food" {
      self.performSegue(withIdentifier: "food", sender: self.customer)
      }
    if choice == "Beverage" {
      self.performSegue(withIdentifier: "beverage", sender: self.customer)
      }
  })
}

我通过prepareForSegue发送数据:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "food" {
        if let foodVC = segue.destination as? FoodVC {
            storyboard?.instantiateViewController(withIdentifier: "food")
            foodVC.customerToEdit = self.customerToEdit
            foodVC.delegate = self
        }
    }

    if segue.identifier == "beverage" {
        if let beverageVC = segue.destination as? BeverageVC {
            storyboard?.instantiateViewController(withIdentifier: "beverage")
            beverageVC.customerToEdit = self.customerToEdit
            beverageVC.delegate = self
        }
    }
}

所以现在所有内容都正确加载和查看:)