如何在UITableView中隐藏amount为0的resource类实例
问题描述
我有一个包含多个属性的resource类,核心需求是在UITableView中仅展示amount属性大于0的类实例,不显示空值。关键约束是不能通过编程方式创建新数组,否则会破坏现有大型应用。目前仅对UITableView的cell做了调整,相关代码如下:
类数组与视图控制器代码
var allResources = [m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17, f18, f19, f20, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. f3.amount += 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return allResources.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath) if allResources[indexPath.row].amount > 0 { cell.textLabel?.text = "\(allResources[indexPath.row].name)" cell.detailTextLabel?.text = "\(allResources[indexPath.row].amount)" } return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { allResources.remove(at: 0) tableView.deleteRows(at: [indexPath], with: .fade) }
resource类部分代码
class resource { var name: String var type: String var value: Int var edible: Bool var buildingMaterial: Bool var craftsMaterial: Bool var toolMaterial: Bool var amount: Int = 0 init(name: String, type: String, value: Int, edible: Bool, buildingMaterial: Bool, craftsMaterial: Bool, toolMaterial: Bool, amount: Int) { self.name = name self.type = type self.value = value self.edible = edible self.buildingMaterial = buildingMaterial self.craftsMaterial = craftsMaterial self.toolMaterial = toolMaterial self.amount = amount } } // 石灰岩 var m1 = resource(name: "Limestone", type: "Mineral", value: 1, edible: false, buildingMaterial: true, craftsMaterial: true, toolMaterial: true, amount: 0) // 花岗岩 var m2 = resource(name: "Granite", type: "Mineral", value: 20, edible: false, buildingMaterial: true, craftsMaterial: true, toolMaterial: false, amount: 0)
解决方案
核心思路
不创建新元素数组,而是通过实时计算索引映射实现仅展示符合条件的元素:
- 用计算属性实时过滤出
amount>0的元素在原数组中的索引 - 基于这个索引数组驱动UITableView的所有数据源方法
修改后的视图控制器代码
var allResources = [m1, m2, m3, ...] // 原数组保持完全不变 // 计算属性:实时获取符合展示条件的元素在原数组中的索引 private var visibleResourceIndices: [Int] { return allResources.enumerated() .filter { $0.element.amount > 0 } .map { $0.offset } } override func viewDidLoad() { super.viewDidLoad() f3.amount += 1 tableView.reloadData() // 修改amount后必须刷新表格,触发计算属性重新计算 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return visibleResourceIndices.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "CellID", for: indexPath) // 通过索引映射获取原数组中的对应元素 let resourceIndex = visibleResourceIndices[indexPath.row] let targetResource = allResources[resourceIndex] cell.textLabel?.text = targetResource.name cell.detailTextLabel?.text = "\(targetResource.amount)" return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 通过索引映射找到元素在原数组中的真实位置 let resourceIndex = visibleResourceIndices[indexPath.row] allResources.remove(at: resourceIndex) tableView.deleteRows(at: [indexPath], with: .fade) }
关键说明
visibleResourceIndices是计算属性,每次调用都会实时扫描原数组,仅存储符合条件的元素索引,完全满足“不创建新数组”的约束- 任何修改元素
amount的操作后,必须调用tableView.reloadData()更新视图,确保索引映射同步 - 删除操作需通过索引映射找到原数组中的真实位置,避免因过滤导致的索引混乱
内容的提问来源于stack exchange,提问作者Superpig0
相关产品推荐
相关产品推荐

