使用Swift的UITableView实现iPhone设置页面,代码报错如何解决?
UITableView 运行核心逻辑
- 数据源优先:UITableView的所有显示内容都由你实现的DataSource协议方法提供,必须严格和你定义的数据源数组结构对应
- 分组对应逻辑:iPhone设置页是分组样式的UITableView,每一个section对应设置里的一个功能分组,section下的row对应分组内的每一个设置项
- 复用机制:UITableView通过复用identifier复用cell,使用前必须先注册对应identifier的cell类,否则运行时会直接崩溃
代码存在的问题
- 变量名引用错误:你在控制器中定义的数据源数组名为
lines,但所有数据源方法中都调用了不存在的titles变量,直接编译报错 - 模型取值逻辑错误:
Lines是你定义的结构体类型,你赋值时直接写Lines.image/Lines.title取的是类型本身的属性,而不是你数据源中某一个分组、某一行的实例数据 - 系统图片初始化语法错误:调用SF符号的正确写法是
UIImage(systemName: "符号名"),你写的UIImage[ systemName: xxx ]语法完全错误 - 头部视图逻辑错误:
viewForHeaderInSection方法需要返回UIView类型的头部视图,你错误地返回了Cell实例,且iPhone设置的分组头部不需要自定义Cell,直接用系统提供的头部API即可 - 缺少Cell注册步骤:你直接通过identifier复用Cell,但没有在viewDidLoad中注册对应Cell类,运行时会触发崩溃
- 行赋值逻辑错误:取某一行的内容需要按
数据源[section][row]的层级取值,你完全没有取对应indexPath下的具体数据
修正后的完整代码
import UIKit // 模型定义:每一个Lines对应一个设置分组 struct Lines{ var images: [UIImage] // 分组内所有行的图标 var titles: [String] // 分组内所有行的标题 } class Titles { // 生成所有分组的数据源 static func getSections() -> [Lines]{ return [ Lines( images: [ UIImage(systemName: "airplane")!, UIImage(systemName: "wifi.square.fill")!, UIImage(systemName: "bitcoinsign.circle.fill")!, UIImage(systemName: "iphone.homebutton.radiowaves.left.and.right")!, UIImage(systemName: "personalhotspot")! ], titles: ["飞行模式" , "Wi-Fi", "蓝牙", "蜂窝网络", "个人热点"] ), Lines( images: [ UIImage(systemName: "bell.badge.fill")!, UIImage(systemName: "speaker.wave.3.fill")!, UIImage(systemName: "moon.fill")!, UIImage(systemName: "clock.fill")! ], titles: ["通知", "声音与触感", "专注模式", "屏幕使用时间"] ), Lines( images: [ UIImage(systemName: "gear")!, UIImage(systemName: "switch.2")!, UIImage(systemName: "display")! ], titles: ["通用", "控制中心", "显示与亮度"] ) ] } } class SecondTableViewController: UITableViewController { // 数据源数组 private let sections = Titles.getSections() override func viewDidLoad() { super.viewDidLoad() // 注册自定义Cell,必须和复用的identifier对应 tableView.register(TableViewCell.self, forCellReuseIdentifier: "SecondTableViewCell") // 设置分组样式的行高 tableView.rowHeight = 44 } } // MARK: - UITableViewDataSource & Delegate extension SecondTableViewController { // 返回分组数量 override func numberOfSections(in tableView: UITableView) -> Int { return sections.count } // 返回对应分组的行数 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sections[section].titles.count } // 返回行Cell override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "SecondTableViewCell", for: indexPath) as! TableViewCell // 取当前行对应的数据 let currentSection = sections[indexPath.section] cell.iconView.image = currentSection.images[indexPath.row] cell.titleLabel.text = currentSection.titles[indexPath.row] // 设置右侧箭头,和系统设置一致 cell.accessoryType = .disclosureIndicator return cell } // 点击行后的处理 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) // 这里可以加跳转逻辑 } } // 自定义Cell的实现示例,你需要和你自己的Cell属性对应 class TableViewCell: UITableViewCell { let iconView = UIImageView() let titleLabel = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupUI() { iconView.contentMode = .scaleAspectFit iconView.tintColor = .systemBlue contentView.addSubview(iconView) contentView.addSubview(titleLabel) // 简单布局,你可以根据需要调整 iconView.translatesAutoresizingMaskIntoConstraints = false titleLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ iconView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), iconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), iconView.widthAnchor.constraint(equalToConstant: 24), iconView.heightAnchor.constraint(equalToConstant: 24), titleLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 16), titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor) ]) } }
内容的提问来源于stack exchange,提问作者Kseniia Piskun
相关产品推荐
相关产品推荐

