Swift中TableView的numberOfRowsInSection如何按类别返回不同数组计数
问题分析与解决方案
你的代码出现“点击任意类别都展示所有内容”的问题,核心原因有这几点:
- 错误覆盖了选中类别:在遍历接口返回数据时,你把用来标记用户选中类别的
categoryName用每条账单的类别覆盖了,导致它最后变成了最后一条数据的类别,完全失去了筛选作用。 - 数据结构不合理:所有类别的数据都塞进同一个数组,根本无法区分不同类别的内容。
- 重复添加数据:
print语句里重复调用append,导致同一条数据被添加两次。 - 数据源方法逻辑无效:
numberOfRowsInSection里不管什么条件都返回同一个数组的长度,判断完全起不到筛选作用。
下面是修正后的完整代码:
import UIKit class PaymentTableViewCell: UITableViewCell{ @IBOutlet weak var pamntTypeLabel: UILabel! } class AllMakePaymentViewController: UIViewController { @IBOutlet weak var tableView: UITableView! // 专门接收用户选中的类别(比如从上个页面传过来) var selectedCategory: String? // 用字典存储每个类别对应的账单列表,key是类别名称,value是该类别下的账单名称数组 var categoryItems = [String: [String]]() override func viewDidLoad() { super.viewDidLoad() allPaymentService() } func allPaymentService(){ let urlStr = "https://dev.com/webservices/api.php?rquest" guard let url = URL(string: urlStr) else { print("无效的URL") return } URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in guard let respData = data else { print("无返回数据") return } guard error == nil else { print("请求错误: \(error!)") return } do{ let jsonObj = try JSONSerialization.jsonObject(with: respData, options: .allowFragments) as! [String: Any] guard let billerdetailsArray = jsonObj["billerdetails"] as? [[String: Any]] else { print("解析billerdetails失败") return } // 清空字典,避免重复加载数据 self.categoryItems.removeAll() for billerdetail in billerdetailsArray { // 用临时变量存当前账单的类别,不修改选中类别变量 guard let currentCategory = billerdetail["bcategoryname"] as? String else { continue } guard let bName = billerdetail["bname"] as? String else { continue } // 初始化对应类别的数组(如果不存在) if self.categoryItems[currentCategory] == nil { self.categoryItems[currentCategory] = [] } // 将账单名称添加到对应类别的数组 self.categoryItems[currentCategory]?.append(bName) // 打印对应类别的数组(避免重复调用append) print("\(currentCategory) 数组: \(self.categoryItems[currentCategory]!)") } DispatchQueue.main.async { self.tableView.reloadData() } } catch { print("JSON解析错误: \(error)") } }).resume() } } extension AllMakePaymentViewController: UITableViewDelegate, UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // 返回选中类别对应的数组长度,无选中类别则返回0 guard let category = selectedCategory else { return 0 } return categoryItems[category]?.count ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PaymentTableViewCell guard let category = selectedCategory, let items = categoryItems[category], indexPath.row < items.count else { cell.pamntTypeLabel.text = "" return cell } cell.pamntTypeLabel.text = items[indexPath.row] self.tableView.separatorStyle = .none return cell } }
关键修改说明:
- 优化数据存储:用字典
categoryItems替代单一数组,每个类别对应独立的账单列表,实现精准筛选。 - 保护选中类别:用临时变量
currentCategory存储遍历到的账单类别,不再修改用来标记用户选中类别的selectedCategory。 - 修复重复添加问题:去掉
print语句里的append调用,先添加数据再打印数组内容。 - 完善数据源方法:
numberOfRowsInSection根据selectedCategory返回对应类别的数组长度,无选中类别则返回0。cellForRowAt增加安全校验,避免数组越界崩溃。
- 添加安全判断:对URL初始化、数据解析等环节增加可选绑定,提升代码稳定性。
修改后,只要给selectedCategory传递对应类别(比如"Water"),TableView就只会展示该类别下的内容了。
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

