4. 实现页面导航与数据传递
任务说明
本案例实现一个两页面的iOS导航流程:首页(列表页)展示一组商品名称,点击任意商品后通过导航控制器跳转到详情页,并将该商品的名称与价格传递给详情页进行展示。通过本案例掌握UINavigationController的栈管理、prepare(for:sender:)正向传值以及可选类型的安全解包。
实现方案
采用Storyboard + Segue搭建界面,使用UITableViewController作为首页展示数据源,详情页使用UIViewController承载两个UILabel。在首页的prepare(for:sender:)方法中根据indexPath取出对应模型,赋值给详情页的公开属性。导航控制器由Storyboard的Navigation Controller入口自动创建,无需额外代码。
代码实现
创建两个Swift文件,分别对应首页控制器与详情页控制器。模型使用轻量级struct,数据在首页控制器内部硬编码。
// Product.swift(模型定义)
import Foundation
struct Product {
let name: String
let price: Double
}
// ProductListViewController.swift(首页/列表页)
import UIKit
class ProductListViewController: UITableViewController {
private let products: [Product] = [
Product(name: "机械键盘", price: 399.0),
Product(name: "无线鼠标", price: 129.0),
Product(name: "27寸显示器", price: 1899.0),
Product(name: "USB-C扩展坞", price: 259.0)
]
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductCell", for: indexPath)
let product = products[indexPath.row]
cell.textLabel?.text = product.name
cell.detailTextLabel?.text = String(format: "¥%.0f", product.price)
return cell
}
// MARK: - Navigation(正向传值)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "ShowProductDetail",
let indexPath = tableView.indexPathForSelectedRow,
let detailVC = segue.destination as? ProductDetailViewController else {
return
}
let selectedProduct = products[indexPath.row]
detailVC.product = selectedProduct
}
}
// ProductDetailViewController.swift(详情页)
import UIKit
class ProductDetailViewController: UIViewController {
// 由首页在跳转前赋值
var product: Product?
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var priceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
private func configureUI() {
guard let product = product else {
nameLabel.text = "未知商品"
priceLabel.text = "--"
return
}
nameLabel.text = product.name
priceLabel.text = String(format: "¥%.2f", product.price)
}
}
Storyboard连线配置
在Main.storyboard中完成以下设置:
- 将
Navigation Controller设为Is Initial View Controller,其rootViewController指向ProductListViewController(UITableViewController子类)。 - 列表页的UITableViewCell设置
Style: Subtitle,Identifier: ProductCell,Accessory: DisclosureIndicator。 - 从列表页的TableView Cell(而非控制器)按住Control拖线到详情页
ProductDetailViewController,选择Show类型的Segue,设置Identifier: ShowProductDetail。 - 详情页中放置两个UILabel,分别连接到
nameLabel与priceLabel。
验证方法
使用Xcode 14及以上版本,选择iPhone模拟器(如iPhone 14)运行项目。预期行为:
- 首页表格显示4行商品,每行左侧为名称、右侧为价格(整数格式)。
- 点击“机械键盘”行,页面推入详情页,导航栏出现返回按钮,详情页显示“机械键盘”与“¥399.00”。
- 点击导航栏返回按钮,回到列表页,列表滚动位置保持不变。
判定标准:若点击任意行均能正确显示对应商品的名称与两位小数价格,且返回后列表无异常,则导航与传值功能通过。