Swift: 同时重置多个子类自定义uitableviewcells?

Swift: Reseting multiple subclassed custom uitableviewcells at the same time?

我有 3 个自定义单元格,它们是从 viewController Uitable 视图中子class 编辑的。这些单元格有手势识别器来查看它们在哪里触摸以更改图标/背景,然后将结果保存到核心数据。 我想要这样的情况,当任何单元格没有被触摸 3 秒(删除保存按钮)时,数据被保存并且单元格重置为基色和图形。我已经全部完成,但我无法使用任何方法同时重置它们。我尝试了很多不同的方法,我认为最好的方法是在 viewcontroller 中重新加载 table,但我无法让它工作。 目前我正在使用一个带有布尔值的结构。当触摸在任何单元格上结束时,它会调用一个计时器,如果它在没有另一个触摸的情况下结束,它会调用一个方法来保存和重置。 也许这是错误的方法,所以我有点卡住了。

查看控制器class

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) ->     
Int {
return measurements.count

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

if indexPath.row == 0 {

   let cell = tableView.dequeueReusableCellWithIdentifier("BmCustomCell", forIndexPath: indexPath) as! BmTableViewCell


  return cell

} else if indexPath.row == 1 {


  let cell = tableView.dequeueReusableCellWithIdentifier("StressCustomCell", forIndexPath: indexPath)as! StressTableViewCell


  return cell
} else {


  let cell = tableView.dequeueReusableCellWithIdentifier("PainCustomCell", forIndexPath: indexPath) as! PainTableViewCell

  return cell
      }
}

painTableViewCell 示例class(与其他两个相同)

// if touched the text changes and the icon changes. if not touched for 5 seconds resets to not touched.

func resetTouchedPainAfterFiveSecs (){

if TouchNotification.isBeingTouched == false {
  timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("reset"), userInfo: nil, repeats: false)
} else {
  timer.invalidate()
}
}

func reset(){

ResetTables().resetAllTables()
savePainData()
}


// reset pain ui to ready to go state
func resetPain () {
TouchNotification.reset = true

if TouchNotification.reset == true {
  painLabel.textColor = whiteColour
  painIcon.image = UIImage(named: "IconPain 0 Unused")
  touchedPain = false
  painLabel.text = "Pain"
  TouchNotification.reset = false

}
}

触摸通知

struct TouchNotification {
static var isBeingTouched = false
static var reset = false
}

重置class

class ResetTables: UIViewController {

func resetAllTables(){

StressTableViewCell().resetStress()
BmTableViewCell().resetBM()
PainTableViewCell().resetPain()

}

}

看来问题是您正在创建对象的新实例,而不是使用屏幕上的实例。

举个例子,

ResetTables().resetAllTables()

调用

func resetAllTables(){
  StressTableViewCell().resetStress()
  BmTableViewCell().resetBM()
  PainTableViewCell().resetPain()
}

您对 ResetTables() 所做的是创建 class ResetTables 的新对象,然后对其调用 resetAllTables(),这又会创建一个新单元格 StressTableViewCell,并对其调用 resetStress。其他两个单元格也是如此。尽管您正在 调用这些方法,但您并不是在显示的单元格上调用它们,而是在新的单元格上调用它们,在函数离开作用域后,这些单元格将被释放。

所以在您的 reset() 方法中,您想要重置单元格本身,而不是创建您重置的新单元格。

你说"I thought the best way would be to reload the table in the view controller but I couldn't make it work"。是的,这正是我建议你做的(尽管我可能会建议 reloadRowsAtIndexPaths)。

一个更微妙的问题是,尤其是当您的 UI 变得越来越复杂时,单元格可以滚动到屏幕之外,可以重复使用等等。因此,您通常希望避免直接更新单元格。如果这些单元格中的一个或多个在需要重置时已经滚出屏幕怎么办?当它滚动回视图时,您如何知道如何处理该单元格?等等

因此,您经常希望将 UI(单元格)与模型(关于哪些单元格是什么颜色的信息)分离。一旦你这样做了,你就可以移动到一个你有一些模型结构的世界(在我下面的例子中,cellBackgroundColors),它跟踪一个单元格应该是什么颜色。然后 cellForRowAtIndexPath 将根据此模型对象设置单元格的颜色。然后,每当您想更改单元格的颜色时,您 (a) 更新此模型对象,然后 (b) 告诉 table 视图重新加载该单元格。

如果您想同时更新多个单元格,则可以更新您的模型并使用单元格数组调用 reloadRowsAtIndexPaths,然后它们将同时更新。但是您也将以安全的方式执行此操作,这不依赖于当时屏幕上的单元格。而且,如果我正确地推断您希望计时器在他们点击其他内容时重新启动,您可以 invalidate 计时器并在用户每次点击单元格时创建一个新计时器。

这是一个小例子:

class ViewController: UITableViewController {

    var cellBackgroundColors: [UIColor]!
    let defaultColor = UIColor.whiteColor()

    override func viewDidLoad() {
        super.viewDidLoad()

        resetCellBackgroundColorsToDefault()
    }

    func resetCellBackgroundColorsToDefault() {
        cellBackgroundColors = [UIColor.redColor(), UIColor.yellowColor(), UIColor.cyanColor()]
    }

    // MARK: UITableViewDataSource

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

        // do whatever cell configuration you want here

        // but programmatically set the background color (or whatever) based upon the model:

        if indexPath.row < 3 {
            cell.backgroundColor = cellBackgroundColors[indexPath.row]
        } else {
            cell.backgroundColor = defaultColor
        }

        return cell
    }

    // MARK: UITableViewDelegate

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        tableView.deselectRowAtIndexPath(indexPath, animated: false)

        cellBackgroundColors[indexPath.row] = UIColor.blueColor()

        tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

        timer?.invalidate()
        timer = NSTimer.scheduledTimerWithTimeInterval(3, target: self, selector: "resetCells:", userInfo: nil, repeats: false)
    }

    // MARK: Timer code

    weak var timer: NSTimer?

    func resetCells(timer: NSTimer) {
        resetCellBackgroundColorsToDefault()

        let indexPaths = [0, 1, 2].map { NSIndexPath(forRow: [=10=], inSection: 0) }

        tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: .Fade)
    }

}