【问题标题】:UISwtich is triggring another UISwitch event in UITableViewUISwtich 正在触发 UITableView 中的另一个 UISwitch 事件
【发布时间】:2015-12-21 04:53:52
【问题描述】:

我在PFTableView 中使用UISwitch。当我打开一个 UISwitch 时,它会触发不同单元格中的另一个开关。这是PFTableViewCell的代码。

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject ? ) - > PFTableViewCell {
  var cell = tableView.dequeueReusableCellWithIdentifier("tempHsCell") as!NearestHsCell!

    if cell == nil {
      cell = NearestHsCell(style: UITableViewCellStyle.Default, reuseIdentifier: "tempHsCell")
    }
    /*Assign Object to cell*/
  cell.hotspot = object
  return cell
}

// Code for UISwtich Action  
@
IBAction func userSelectHotspot(sender: UISwitch) {
  if hotspotSwitch.on {
    selectedHotspot[(self._hotspot ? .objectId) !] = self._hotspot
  } else {
    let key = self._hotspot!.objectId!
      selectedHotspot.removeValueForKey(key)
  }
}

【问题讨论】:

  • 您应该通过将开关状态存储在单元格的对象中而不是让它默认来控制您的开关,dequeueReusableCellWithIdentifier 的东西与您的非编码开关重叠,可能还有其他方法可以做,但我不确定: D
  • 发生这种情况时两个开关都在屏幕上,还是您必须滚动才能发现错误触发的开关?如果是这样,那是因为其他人说的细胞重用。您应该每次都将单元格重置为清洁状态。理想情况下,分配您的 hotspot 属性可以通过使用属性观察器来更新单元格状态。
  • @NicolasMiari 我必须向下滚动才能查看第二个开关。但代码在 IBAction 中。您能否在代码中详细说明您的答案。

标签: ios swift uitableview uiswitch


【解决方案1】:

这是因为表格单元格与dequeueReusableCellWithIdentifier 一起重复使用。您需要考虑到这一点并每次都重置开关。

【讨论】:

  • 我认为这不是解决方案。
  • 你好@迈克尔。你能告诉我如何在代码中实现这一点。
【解决方案2】:
//need to maintain Switch status of every cell , using datasource , initially datasource initialize with all elements "NO"

override func tableView(tableView: UITableView, cellForRowAtIndexPathindexPath: NSIndexPath, object: PFObject ? ) - > PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("tempHsCell") as!NearestHsCell!

 if cell == nil {
   cell = NearestHsCell(style: UITableViewCellStyle.Default, reuseIdentifier: "tempHsCell")
}
/*Assign Object to cell*/

if arrDatasource.objectAtIndex(indexPath.row) as! String == "YES" {
  switch.on = true
 } else {
   switch.on = false
}
cell.hotspot = object
switch.tag = indexpath.row
return cell
}

@IBAction func userSelectHotspot(sender: UISwitch) {
  if hotspotSwitch.on {
    arrDatasource.setObject("YES", atIndexedSubscript:sender.tag)
    selectedHotspot[(self._hotspot ? .objectId) !] = self._hotspot
 } else {
   arrDatasource.setObject("NO", atIndexedSubscript:sender.tag)
   let key = self._hotspot!.objectId!
   selectedHotspot.removeValueForKey(key)
}
}

【讨论】:

    【解决方案3】:

    所以,根据您的评论:

    @NicolasMiari 我必须向下滚动才能查看第二个开关。但是 代码在 IBAction 中。您能否在代码中详细说明您的答案。 – 尼山特·东加雷

    ...似乎该单元格正在被重复使用,因此开关保持“打开”状态,因为当该单元格用于显示索引 #0 处的行并且您点击它时。

    为避免在重复使用单元格时保留任何先前的状态,应始终在重复使用之前将其重置:

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject ? ) - > PFTableViewCell {
      var cell = tableView.dequeueReusableCellWithIdentifier("tempHsCell") as!NearestHsCell!
    
        if cell == nil {
            // Cell is brand new, no need to clean up:
    
            cell = NearestHsCell(style: UITableViewCellStyle.Default, reuseIdentifier: "tempHsCell")
        }
        else{
            // Cell is being reused; reset all subviews/state etc.
    
            cell.switch.on = false
        }
    
        /*Assign Object to cell*/
        cell.hotspot = object
    
        return cell
    }  
    

    (作为旁注,我强烈建议您改用 dequeueReusableCellWithIdentifier(_: forIndexPath:);它会自动为您进行实例化,以防池中没有单元格可重用,因此您的代码变得更短更简单)

    或者,您可以在分配模型对象时让单元格处理它:

    class NearestCell : UITableViewCell {
    
        var hotSpot:<(The Class of hotspot)> {
            didSet {
                // (Update state of the switch, cell's title label, etc.
                // based on the new value of hotspot.)
            }
        } 
    

    【讨论】:

    • 你好@NicolasMiari。我尝试了这两种方法。 if cell == nil { // Cell is brand new, no need to clean up: cell = NearestHsCell(style: UITableViewCellStyle.Default, reuseIdentifier: "tempHsCell") } else{ // Cell is being reused; reset all subviews/state etc. cell.switch.on = false } 它正在工作。但不利的一面是,当我向下滚动并再次向上滚动时,选定的 Swtich 也会被取消选择。
    • 那是因为你的数据模型没有“记住”开关状态。我的猜测是,当您翻转开关时,与单元关联的热点对象应该存储该状态。下次您将相同的热点对象分配给新单元格时,该单元格必须相应地更新其子视图(即,将开关设置为打开)。有意义吗?
    • 细胞被重复使用以提高效率;在任何时候,只存在 scrren 上需要的实例数。您的单元格必须能够恢复与显示数据模型的给定行相关的任何状态。
    • 在您的情况下,您应该在开关更改状态时(在关联的@IBAction 内)修改单元格热点的属性,以便下次将该热点分配给不同的重用单元格,它可以将开关设置为适当的状态并保持一致性。
    【解决方案4】:

    我在一组 UITableViewCell 单元格中遇到了多个 UISwitches 的类似问题。它是堆叠在其他人之上的“addTarget”。在解决之前删除它们。

    cell.optionSwitch.on = configManager.distanceMetric;
    [cell.optionSwitch removeTarget:self action:nil 
     forControlEvents:UIControlEventTouchUpInside];
    [cell.optionSwitch addTarget:self action:@selector(updateDistanceMetric:)
     forControlEvents:UIControlEventTouchUpInside];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多