如何完成TableView选择和segue到下一个ViewController之间的功能?
我的应用程序具有以下流程:
- 视图控制器 1 呈现带有标题的 TableView
- 用户选择 TableView 行
- 视图控制器 1 指示模型加载所选 TableView 行的完整数据
- 模型将数据传递回视图控制器 1
- 视图控制器 1 将该数据传递给视图控制器 2作为 segue 的一部分
这就是我将数据传递到 View Controller 2 的方式:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? UINavigationController else {
return
}
guard let finalDestination = destination.viewControllers.first as? SegmentedControlViewController else {
return
}
if let indexPath = tableView.indexPathForSelectedRow {
let documentId = documentIdArray[indexPath.row]
finalDestination.documentId = documentId
print(documentID) // documentId is not nil and is passed to the next view controller successfully
model.getRecipeSelected(docId: documentId) // the output of this is entireRecipe
finalDestination.entireRecipe = entireRecipe
print(entireRecipe) // entireRecipe is nil
}
}
应用程序崩溃,因为 View Controller 2 正在尝试处理尚不存在的数据。如何确保 model.getRecipeSelected(docId: documentId)
获取数据并将其传递给 View Controller 2 在之前?
注意:我已确认将 model.getRecipeSelected(docId: documentId)
放入我的 viewDidLoad()
中可以正常工作。问题似乎是在转至视图控制器 2 之前,它尚未检索/传递数据。
编辑:我也尝试了以下操作,但没有成功。 >
<强>1。向我的模型添加了一个完成处理程序,并在准备函数中执行所有操作。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MealPlanToSegmentedControl" {
guard let destination = segue.destination as? UINavigationController else {
return
}
guard let finalDestination = destination.viewControllers.first as? SegmentedControlViewController else {
return
}
if let indexPath = tableView.indexPathForSelectedRow {
let documentID = recipeDocIdArray[indexPath.row]
finalDestination.passedDocID = documentID
model.getRecipeSelected(docId: documentID) {
print("(entireRecipe)") // FIXME: SEGUE HAPPENS BEFORE entireRecipe IS ASSIGNED ANY DATA
finalDestination.entireRecipe = entireRecipe
}
}
}
}
2.向我的模型添加了一个完成处理程序并使用 didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let documentID = recipeDocIdArray[indexPath.row]
model.getRecipeSelected(docId: documentID) {
self.performSegue(withIdentifier: "MealPlanToSegmentedControl", sender: Any?.self)
}
}
My app has the following flow:
- View Controller 1 presents TableView with Titles
- User selects TableView row
- View Controller 1 instructs Model to load the full data for that selected TableView row
- Model passes data back to View Controller 1
- View Controller 1 passes that data View Controller 2 as part of a segue
This is how I'm passing data to the View Controller 2:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? UINavigationController else {
return
}
guard let finalDestination = destination.viewControllers.first as? SegmentedControlViewController else {
return
}
if let indexPath = tableView.indexPathForSelectedRow {
let documentId = documentIdArray[indexPath.row]
finalDestination.documentId = documentId
print(documentID) // documentId is not nil and is passed to the next view controller successfully
model.getRecipeSelected(docId: documentId) // the output of this is entireRecipe
finalDestination.entireRecipe = entireRecipe
print(entireRecipe) // entireRecipe is nil
}
}
The app crashes because View Controller 2 is trying to work off of data that isn't there yet. How can I make sure model.getRecipeSelected(docId: documentId)
gets the data and passes it to View Controller 2 before I segue to it?
Note: I've confirmed that model.getRecipeSelected(docId: documentId)
works by putting it in my viewDidLoad()
. The issue seems to be that it hasn't retrieved/passed the data before the segue to View Controller 2.
Edit: I've also tried the following but with no success.
1. Added a completion handler to my model and do everything in prepare function.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MealPlanToSegmentedControl" {
guard let destination = segue.destination as? UINavigationController else {
return
}
guard let finalDestination = destination.viewControllers.first as? SegmentedControlViewController else {
return
}
if let indexPath = tableView.indexPathForSelectedRow {
let documentID = recipeDocIdArray[indexPath.row]
finalDestination.passedDocID = documentID
model.getRecipeSelected(docId: documentID) {
print("(entireRecipe)") // FIXME: SEGUE HAPPENS BEFORE entireRecipe IS ASSIGNED ANY DATA
finalDestination.entireRecipe = entireRecipe
}
}
}
}
2. Added a completion handler to my model and use didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let documentID = recipeDocIdArray[indexPath.row]
model.getRecipeSelected(docId: documentID) {
self.performSegue(withIdentifier: "MealPlanToSegmentedControl", sender: Any?.self)
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
didReceiveRecipe(recipe:)
,这将更新配方属性并将您的模型设置为 VC1 的委托。更新菜谱后,现在还调用performSegue
,当您到达调用prepare(for:sender:)
时,您肯定会拥有可用的菜谱。didSelectRow
委托方法中,要求您的模型获取配方,这样做时将调用委托方法。didReceiveRecipe(recipe:)
which will update the recipe property and set your model as the delegate for VC1. After updating the recipe, also callperformSegue
now and when you reach the point ofprepare(for:sender:)
gets called, you will definitely have your recipe available.didSelectRow
delegate method, ask your model to fetch the recipe which on doing so will call the delegate method.