You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中TableView的numberOfRowsInSection如何按类别返回不同数组计数

问题分析与解决方案

你的代码出现“点击任意类别都展示所有内容”的问题,核心原因有这几点:

  1. 错误覆盖了选中类别:在遍历接口返回数据时,你把用来标记用户选中类别的categoryName用每条账单的类别覆盖了,导致它最后变成了最后一条数据的类别,完全失去了筛选作用。
  2. 数据结构不合理:所有类别的数据都塞进同一个数组,根本无法区分不同类别的内容。
  3. 重复添加数据:print语句里重复调用append,导致同一条数据被添加两次。
  4. 数据源方法逻辑无效: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:26:50