我的表格视图单元格显示具有两个不同按钮元素的实体。我希望能够启动一个视图控制器,如果我点击第一个按钮,则会显示一系列食物项目,而另一个视图控制器会在我点击第二个按钮时显示一系列饮料。
我能够正确地将数据传递给新的视图控制器,但似乎无法关闭当前视图并加载新视图。我的代码是这样的:
在表格视图单元格
中 @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")
}
答案 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
}
}
}
所以现在所有内容都正确加载和查看:)