Ios 仅在表视图的特定单元格上显示和隐藏视图
我有一个带有自定义单元格的表视图。它们非常高,因此只有一个单元格在屏幕上完全可见,并且可能根据该单元格的位置,第二个单元格的顶部25%。这些单元格表示具有名称的虚拟项。每个单元格内都有一个按钮。第一次点击时,它会在单元格内显示一个小的Ios 仅在表视图的特定单元格上显示和隐藏视图,ios,arrays,swift,uitableview,uiview,Ios,Arrays,Swift,Uitableview,Uiview,我有一个带有自定义单元格的表视图。它们非常高,因此只有一个单元格在屏幕上完全可见,并且可能根据该单元格的位置,第二个单元格的顶部25%。这些单元格表示具有名称的虚拟项。每个单元格内都有一个按钮。第一次点击时,它会在单元格内显示一个小的UIView,并将该项添加到数组中,第二次点击时,它会隐藏该项并删除该项。添加和删除项的部分工作正常,但是,由于在UITableView 当我添加视图时,例如,在第一个单元格、第三个或第四个单元格上(在重复使用该单元格之后),我仍然可以看到该视图 为了防止这种情况,
UIView
,并将该项添加到数组中,第二次点击时,它会隐藏该项并删除该项。添加和删除项的部分工作正常,但是,由于在UITableView
当我添加视图时,例如,在第一个单元格、第三个或第四个单元格上(在重复使用该单元格之后),我仍然可以看到该视图
为了防止这种情况,我尝试循环项目数组,并对照每个单元格的名称标签文本检查它们的名称。我知道这种方法不是很有效(如果有数千种呢?),但我还是尝试过
下面是它的简单代码(checkedItems
是项目数组,视图应该可见):
乍一看,这段代码运行良好,但在深入挖掘之后,一些问题出现了。当我点击第一个单元格显示视图,然后点击第二个单元格也显示视图时,它工作正常。但是,当我点击第一个和第三个单元格时,第一个单元格上的视图将消失,但该项仍在数组中。我怀疑,原因仍然是细胞被重用的事实,因为细胞的高度非常大,所以第一个细胞在第三个细胞被重用时不可见。我尝试在tableView(:,cellForRow:)
和tableView(:,willDisplay:,forRowAt:)
方法中使用上面的代码,但结果是一样的
因此,问题是:我需要找到一种有效的方法来检查单元格,并且只在checkedItems
数组中的项目内部显示视图
已编辑
下面是有视图和没有视图时单元格的外观(紫色圆圈是按钮,视图是橙色的)
下面是按钮的代码:
protocol ItemTableViewCellDelegate: class {
func cellCheckButtonDidTapped(cell: ExampleTableViewCell)
}
在单元内部:
@IBAction func checkButtonTapped(_ sender: UIButton) {
delegate?.cellCheckButtonDidTapped(cell: self)
}
在视图控制器内部(注意:这里的代码只是显示和隐藏视图。代码的目的是显示按钮如何与表视图进行交互
):
编辑2
下面是tableView(cellForRowAt:)
方法的完整代码(我已经从问题中删除了循环部分,以明确该方法最初的作用)。单元格上的item
属性只设置项的名称(itemnamelab
的text
)
我已经尝试过这个解决方案,但这对我不起作用
如果您遇到过这样的问题,并且知道如何解决它,我将非常感谢您的帮助和建议 我会将单个单元格的状态作为每个单元格后面的modeldata的一部分 我假设您有一个模型对象数组,在
tableview(quot;,cellForRow:)
中填充tableview时使用该数组。该模型是从某个后端服务填充的,该服务为您提供一些JSON,然后在第一次加载视图时将其映射到模型对象
如果向模型对象添加一个属性,指示是否已按下单元,则可以在填充单元时使用该属性
您可能应该创建一个包含原始JSON数据的“包装器对象”,然后创建一个包含状态的变量,让我们称之为ishiden
。您可以使用Bool
值,也可以使用enum
值(如果您愿意)。下面是一个仅使用Bool
struct MyWrappedModel {
var yourJSONDataHere: YourModelType
var isHidden = true
init(yourJSONModel: YourModelType) {
self.yourJSONDataHere = yourJSONModel
}
}
在任何情况下,当您的单元格被点击时(在didSelectRow
中),您将:
MyWrappedModel
对象ishiden
值reloadRows(at:with:)在表视图中重新加载受影响的行。
tableView(:,cellForRow:)
中,您现在可以检查ishiden
,并基于此执行一些渲染:
...//fetch the modelObject for the current IndexPath
cell.checkedView.isHidden = modelObject.isHidden
此外,要知道该方法存在于UITableViewCell
上。当某个单元即将被回收时,就会调用此方法。这意味着您可以在呈现表视图单元格之前将其作为“初始化”表视图单元格的最后手段。因此,在您的情况下,可以将checkedView
作为默认值隐藏
如果您这样做,您就不再需要使用数组来跟踪哪些单元格已被点击。它自己知道模型数据的状态,并且完全独立于单元位置和循环
希望这有帮助。试试这个
全局定义:var arrIndexPaths=NSMutableArray()
您想显示您点击的单元格视图和其他单元格视图是否隐藏?@Kuldeep,是的。视图应仅在第一次点击按钮的单元格中可见。所以,基本上,我的意思是,在一个单元格中显示和隐藏视图,不应该影响其他单元格。这样做:1。在数组中添加被点击的单元格
indexath
,然后重新加载UITableView
并在cellForRow
方法中检查if([arrIndexpaths constansobject:indexath]){show your view}或者{hide your view}
@Kuldeep,问题是,当我点击按钮时,单元格本身没有被点击,所以我无法得到它的indepath
我更新了我的答案,请检查一下。谢谢你的建议。这确实可行,但我有一个问题:如果数据来自JSON怎么办?我是说,如果JSON是我做的
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier:
ItemTableViewCell.identifier, for: indexPath) as? ItemTableViewCell{
cell.item = items[indexPath.row]
cell.delegate = self
cell.selectionStyle = .none
return cell
}
return UITableViewCell()
}
struct MyWrappedModel {
var yourJSONDataHere: YourModelType
var isHidden = true
init(yourJSONModel: YourModelType) {
self.yourJSONDataHere = yourJSONModel
}
}
...//fetch the modelObject for the current IndexPath
cell.checkedView.isHidden = modelObject.isHidden
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 30
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tblVW.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.textLabel?.text = String.init(format: "Row %d", indexPath.row)
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
if arrIndexPaths.contains(indexPath) {
cell.backgroundColor = UIColor.red.withAlphaComponent(0.2)
}
else {
cell.backgroundColor = UIColor.white
}
return cell;
}
@IBAction func btnTapped(_ sender: UIButton) {
let selectedIndexPath = NSIndexPath.init(row: sender.tag, section: 0)
// IF YOU WANT TO SHOW SINGLE SELECTED VIEW AT A TIME THAN TRY THIS
arrIndexPaths.removeAllObjects()
arrIndexPaths.add(selectedIndexPath)
self.tblVW.reloadData()
}