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

时间:2016-01-06 22:58:31

标签: swift uitableview reset custom-cell

我有3个自定义单元格,这些单元格是从它们所在的viewController Uitableview中进行子类化的。单元格具有手势识别器,可以看到它们被触摸的位置以更改图标/背景,然后将结果保存到核心数据。 我希望保存数据的情况,并且当任何单元格未被触摸3秒钟时(删除保存按钮),单元格将重置为基色和图形。我已经完成了所有工作,但是我无法使用任何方法在同一时间重置它们。我尝试了很多不同的方法,我认为最好的方法是在viewcontroller中重新加载表,但我无法使其工作。 目前我正在使用一个触摸布尔的结构。当触摸在任何单元格上结束时,它会调用计时器,如果它在没有其他触摸的情况下结束,则会调用保存和重置的方法。 也许这是错误的做法,所以我有点卡住了。

storyboard

查看控制器类

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类的示例(与其他两个相同)

// 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

}
}

TouchNotification

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

重置课程

class ResetTables: UIViewController {

func resetAllTables(){

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

}

}

2 个答案:

答案 0 :(得分:2)

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

举个例子,

if (partsX[0] < partsY[0]) return -1; else if (partsX[0] > partsY[0]) return 1; else if (partsX[1] < partsY[1]) return -1; else if (partsX[1] > partsY[1]) return 1; else return 0;

调用

ResetTables().resetAllTables()

您正在使用func resetAllTables(){ StressTableViewCell().resetStress() BmTableViewCell().resetBM() PainTableViewCell().resetPain() } 创建的对象是创建类ResetTables()的新对象,然后在其上调用ResetTables,然后创建一个新单元{{1} },并在其上调用resetAllTables()。其他两个细胞也是如此。虽然 调用方法,但您不是在显示的单元格上调用它们,而是在新函数上调用它们,在函数离开作用域之后,将其取消分配。

因此,在StressTableViewCell方法中,您希望重置单元格本身,而不是创建重置的新单元格。

答案 1 :(得分:1)

你说“我认为最好的方法是在视图控制器中重新加载表,但我无法使其工作”。是的,这正是我建议你做的事情(虽然我可能会建议reloadRowsAtIndexPaths)。

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

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

如果要同时更新多个单元格,则更新模型并使用单元格数组调用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: $0, inSection: 0) }

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

}