Swift: одновременный сброс нескольких пользовательских подклассов uitableviewcells?

У меня есть 3 пользовательские ячейки, которые разделены на подклассы из viewController Uitableview, в котором они находятся. Ячейки имеют распознаватель жестов, чтобы видеть, где они касаются, чтобы изменить значки / фоны, после чего результат сохраняется в основных данных. Я хочу иметь ситуацию, когда данные сохраняются и ячейки сбрасываются на базовые цвета и графику, когда ни одна ячейка не затрагивается, скажем, в течение 3 секунд (чтобы удалить кнопку сохранения). У меня все хорошо, но я не могу найти способ сбросить их все в одно и то же время. Я пробовал так много разных способов, и я подумал, что лучший способ будет перезагрузить таблицу в viewcontroller, но я не мог заставить его работать. На данный момент я использую Struct с затронутым bool. Когда касание заканчивается в любой ячейке, оно вызывает таймер, а если оно заканчивается без другого касания, оно вызывает метод сохранения и сброса. Может быть, это неправильный способ сделать это, поэтому я немного застрял.

раскадровка

Посмотреть класс контроллера

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 ответа

Решение

Вы говорите: "Я думал, что лучшим способом было бы перезагрузить таблицу в контроллере представления, но я не мог заставить ее работать". Да, это именно то, что я бы предложил вам сделать (хотя я мог бы предложить reloadRowsAtIndexPaths вместо).

Гораздо более тонкая проблема заключается в том, что, особенно когда ваш пользовательский интерфейс становится все более сложным, ячейки могут прокручиваться за пределы экрана, могут использоваться повторно и т. Д. В результате вы, как правило, хотите избегать непосредственного обновления ячеек. Что, если одна или несколько из этих ячеек прокрутились за пределы экрана к тому времени, когда их необходимо сбросить? Как, когда он снова перейдет в поле зрения, вы узнаете, что делать с этой клеткой? И т.п.

Из-за этого вы часто хотите отделить пользовательский интерфейс (ячейки) от модели (информация о том, какие ячейки какого цвета). Как только вы это сделаете, вы можете перейти в мир, в котором у вас есть некоторая модель структуры (в моем примере ниже, cellBackgroundColors) который отслеживает, какого цвета должна быть клетка. cellForRowAtIndexPath Затем установим цвет ячейки на основе этого модельного объекта. Затем, всякий раз, когда вы хотите изменить цвет ячейки, вы (а) обновляете этот объект модели, а затем (б) говорите табличному представлению перезагрузить эту ячейку.

Если вы хотите обновить несколько ячеек одновременно, обновите модель и позвоните 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)
    }

}

Похоже, проблема в том, что вы создаете новые экземпляры объектов вместо того, чтобы использовать экземпляры на экране.

Взять, к примеру,

ResetTables().resetAllTables()

какие звонки

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

Что вы делаете с ResetTables() создает новый объект класса ResetTables, а затем позвонив resetAllTables() на нем, что, в свою очередь, создает новую ячейку, StressTableViewCell и звонки resetStress в теме. То же самое относится и к двум другим ячейкам. Хотя вы вызываете методы, вы вызываете их не в отображаемых ячейках, а в новых ячейках, которые после выхода из области видимости освобождаются.

Так в вашем reset() метод, вы хотите сбросить саму ячейку, а не создавать новые ячейки, которые вы сбрасываете.

Другие вопросы по тегам