如何解决如何点击 TableView Cell 并导航到下一个 ViewController本地 JSON 文件中的另一个 TableView
我在我的 Xcode 项目中本地保存了以下 JSON 文件。
{
"mealPlan": [
{
"title": "Meal One","instructions": [
"This is step number 1 for Meal One.","This is step number 2 for Meal One.","This is step number 3 for Meal One.","This is step number 4 for Meal One."
]
},{
"title": "Meal Two","instructions": [
"This is step number 1 for Meal Two.","This is step number 2 for Meal Two.","This is step number 3 for Meal Two.","This is step number 4 for Meal Two."
]
}
]
}
以下是我的 MealPlan
和 MealPlanService
结构:
struct MealPlan: Decodable {
var title:String?
var instructions:[String]?
}
struct MealPlanService: Decodable {
var mealPlan:[MealPlan]?
}
在我的第一个 ViewController 中,我已经通过 UITableViewCell 的自定义子类成功地显示了一个带有我的膳食计划标题(例如“膳食一”和“膳食二”)的 TableView。
class MealPlanCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
var mealPlanTodisplay:MealPlan?
func displayMealPlan(_ mealPlan:MealPlan) {
// Keep a reference to the mealPlan
mealPlanTodisplay = mealPlan
// Set the titleLabel
titleLabel.text = mealPlan.title
}
在 ViewController 中:
class ViewController: UIViewController {
var model = MealPlanModel()
var mealPlan = [MealPlan]()
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Set ViewController as the datasource and delegate of the tableView
tableView.delegate = self
tableView.dataSource = self
// Use MealPlanModel to get the mealPlans from the JSON File
model.delegate = self
model.getMealPlans()
}
override func prepare(for segue: UIStoryboardSegue,sender: Any?) {
// Detect the indexPath the user selected
let indexPath = tableView.indexPathForSelectedRow
guard indexPath != nil else {
// The user hasn't selected anything
return
}
// Get the mealPlan the user selected
let mealPlanSelected = mealPlan[indexPath!.row]
// Get a reference to the InstructionViewController
let instructionVC = segue.destination as! InstructionViewController
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
return mealPlan.count
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Get a cell
let cell = tableView.dequeueReusableCell(withIdentifier: "MealPlanCell",for: indexPath) as! MealPlanCell
// Get the mealPlan that the tableView is asking about
let mealPlanInTable = mealPlan[indexPath.row]
// Customize the cell
cell.displayMealPlan(mealPlanInTable)
// Return the cell
return cell
}
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
}
}
extension ViewController: MealPlanProtocol {
func mealPlansRetrieved(_ mealPlans: [MealPlan]) {
print("MealPlan retrieved from model (ViewController).")
// Set the mealPlans property of the ViewController to the mealPlans passed back from the model
self.mealPlan = mealPlans
// Refresh the tableView
tableView.reloadData()
}
}
有两件事我花了很多时间搜索/尝试但仍然无法弄清楚。
- 如何将我的
instructions
数组中的项目显示到表格中
我使用相同的模型来显示第一个 ViewController 中的 mealPlan
和第二个 ViewController 中的 instructions
。
protocol MealPlanProtocol {
func mealPlansRetrieved(_ mealPlans:[MealPlan])
}
class MealPlanModel {
var delegate:MealPlanProtocol?
func getMealPlans() {
// Fetch mealPlans from MealPlansData.json
getLocalJsonFile()
}
func getLocalJsonFile() {
// Get bundle path to the MealPlansData.json
let path = Bundle.main.path(forResource: "MealPlansData",ofType: "json")
// Double check that the path isn't nil
guard path != nil else {
print("Could not find MealPlansData.json.")
return
}
// Create URL object from the path
let url = URL(fileURLWithPath: path!)
do {
// Get the data from the URL
let data = try Data(contentsOf: url)
// Attempt to parse MealPlansData.json into objects
let decoder = JSONDecoder()
let mealPlanService = try decoder.decode(MealPlanService.self,from: data)
// Get the Meal Plans
let mealPlans = mealPlanService.mealPlan!
// Get the Instructions
let instructions = [MealPlan().instructions]
// Notify the delegate of the parsed mealPlanService objects
dispatchQueue.main.async {
self.delegate?.mealPlansRetrieved(mealPlans)
}
}
catch {
// Error: Could not download the data at that URL
print("Could not download the data at that URL.")
}
}
}
但我为第二个 ViewController 使用了 UITableViewCell 的不同自定义子类。
class InstructionCell: UITableViewCell {
@IBOutlet weak var instructionLabel: UILabel!
var mealPlanTodisplay:MealPlan?
let mealPlan = MealPlan()
func displayInstruction(_ currentMealPlan:MealPlan) {
// Keep a reference to the mealPlan
mealPlanTodisplay = currentMealPlan
// Get the instructions data
var instruction = mealPlan.instructions
// Set the instructionLabel
instructionLabel.text = currentMealPlan.instructions![]
}
这是我希望 instructions
在表格视图中显示的第二个 ViewController。
class InstructionViewController: UIViewController {
var model = MealPlanModel()
var mealPlan = [MealPlan]()
var instructions = [MealPlan().instructions]
var currentMealPlanIndex = 0
var currentInstructionIndex = 0
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Set InstructionViewController as the datasource and delegate of the tableView
tableView.delegate = self
tableView.dataSource = self
// Use the InstructionModel to get the instructions from the JSON file
model.delegate = self
model.getMealPlans()
}
}
extension InstructionViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
// Make sure the MealPlan array contains at least 1 instruction
// Todo: - Get the instructions from the selected mealPlan
let instructionsInMealPlan = instructions
guard instructionsInMealPlan.count > 0 else {
return 0
}
return instructionsInMealPlan.count
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Get a cell
let cell = tableView.dequeueReusableCell(withIdentifier: "InstructionCell",for: indexPath) as! InstructionCell
// Get the instruction that the tableView is asking about
// Todo: - Specify the mealPlan that was selected in ViewController
let instructionInTable = mealPlan[indexPath.row].instructions![indexPath.row]
// Customize the cell
cell.displayInstruction(mealPlan[0])
// Return the cell
return cell
}
在 InstructionCell
中,我不确定如何从我的 JSON 文件中获取 instructions
数据。我试图像在 mealPlan
中所做的一样获取 MealPlanCell
数据,但为了深入研究,我尝试调用 mealPlan.instructions
。似乎我没有正确获得“数组的数组”(例如 instructions
数组的 mealPlan
数组)。
- 如何使用适当的
instructions
集填充表视图。例如,我想在第一个 ViewController 中点击 mealPlan[0] 以在第二个 ViewController 中给我 mealPlan[0].instructions。现在我有一个从第一个 ViewController 中的 TableView 单元格导航到第二个 ViewController 的一般过渡。我似乎应该使用func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath)
来获取一组特定的说明,但我并不完全确定。
非常感谢任何帮助!
解决方法
我相信你应该这样做。
在第一个 ViewController(有饭桌视图的那个)中,像这样添加 didSelectRowAtMethod
:
func tableView(_ tableView: UITableView,didSelectRowAt indexPath: IndexPath) {
let selectedMeal = mealPlan[indexPath.row] //this the mealPlan you selected
let detailVC = storyboard?.instantiateViewController(withIdentifier: "VCIdentifier") as! InstructionViewController
detailVC.meal = selectedMeal
present(detailVC,animated: true,completion: nil)
}
您的detailViewcontroller
(显示说明的那个)应该看起来与餐点ViewController
非常相似。您需要一个 tableView 来显示单元格中指令数组中的每条指令。
详细视图控制器代码:
class DetailViewController: UIViewController{
weak var meal: MealPlan?
@IBOutlet weak var tableView: UITableView!
override func ViewDidLoad(){
super.ViewDidLoad()
tableView.delegate = self
tableView.datasource = self
}
}
extension DetailViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
return meal.instructions.count
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID") as! InstructionCell
cell.instruction = meal.instruction[indexPath.row]
cell.displayInstruction()
return cell
}
}
快到了!! 最后一件事。您只需要将单个指令传递给指令单元。 像这样编辑指令单元代码
class InstructionCell: UITableViewCell {
@IBOutlet weak var instructionLabel: UILabel!
var instruction: String?
func displayInstruction() {
// Set the instructionLabel
instructionLabel.text = instruction
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。