Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 仅在表视图的特定单元格上显示和隐藏视图_Ios_Arrays_Swift_Uitableview_Uiview - Fatal编程技术网

Ios 仅在表视图的特定单元格上显示和隐藏视图

Ios 仅在表视图的特定单元格上显示和隐藏视图,ios,arrays,swift,uitableview,uiview,Ios,Arrays,Swift,Uitableview,Uiview,我有一个带有自定义单元格的表视图。它们非常高,因此只有一个单元格在屏幕上完全可见,并且可能根据该单元格的位置,第二个单元格的顶部25%。这些单元格表示具有名称的虚拟项。每个单元格内都有一个按钮。第一次点击时,它会在单元格内显示一个小的UIView,并将该项添加到数组中,第二次点击时,它会隐藏该项并删除该项。添加和删除项的部分工作正常,但是,由于在UITableView 当我添加视图时,例如,在第一个单元格、第三个或第四个单元格上(在重复使用该单元格之后),我仍然可以看到该视图 为了防止这种情况,

我有一个带有自定义单元格的表视图。它们非常高,因此只有一个单元格在屏幕上完全可见,并且可能根据该单元格的位置,第二个单元格的顶部25%。这些单元格表示具有名称的虚拟项。每个单元格内都有一个按钮。第一次点击时,它会在单元格内显示一个小的
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
中),您将:

  • 在基于索引XPath的包装模型数据对象数组中找到正确的
    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()
    }