Использование степпера в ячейке табличного представления, но данные, возвращаемые в VC, не обновляются правильно

Я пытаюсь создать экран конфигурации, чтобы пользователь мог настроить количество тренировок, которые он или она хочет выполнить. Мне удалось добавить табличное представление в пустой контроллер представления, но были некоторые стилистические ограничения, такие как расширение и свертывание табличного представления в зависимости от количества ячеек.

Поэтому я решил настроить экран в формате tableviewcontroller. Теперь все идет хорошо, пока я не дойду до точки, когда я хочу, чтобы мой Stepper в section 0, cell 1 увеличивал и уменьшал количество строк в section 1. Это работает до такой степени, что массив данных (workouts[]) обновляет контроллер представления последним значением (в методе cellForRowAt:indexPath), который, в свою очередь, обновляет numberOfRowsInSection (предположительно) последним workouts.count.

Однако оказывается, что workouts.count содержит счетчик до того, как массив был обновлен степпером последним.

Теперь я пробовал несколько обходных путей, но я все еще не могу правильно обновить метод numberOfRowsInSection - мне кажется, что массив Workouts не обновляется в контроллере представления с последним значением, а с предыдущим установленным значением.

Это мой контроллер представления:

class AViewController: UITableViewController {

//MARK: Properties
@IBOutlet weak var aTableView: UITableView!

var sections: [String] = ["", "Set Up Circuits"]
var workouts: [Exercise] = []

//MARK: Initialisation
override func viewDidLoad() {
    super.viewDidLoad()
    workouts = [Exercise(name: "Circuit 1", timeMinutes: 2)]
    self.tableView.delegate = self
    self.tableView.dataSource = self
}

//MARK: Table Config
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return self.sections[section]
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    switch section {
    case 0:
        return 0.1
    default:
        return 32.0
    }
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    switch indexPath.section {
    case 0:
        return 60
    default:
        return 44
    }
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    var numberOfRowsInSection: Int = 0

    switch section {
    case 0:
        numberOfRowsInSection = 1
    default:
        numberOfRowsInSection = workouts.count
        //numberOfRowsInSection = 1
    }
    print(numberOfRowsInSection, "number of rows in section", section)
    return numberOfRowsInSection
}

//MARK: Table Protocols
override func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {

    //Setting layout for circuit number config
    case 0:
        let cell = aTableView.dequeueReusableCell(withIdentifier: "ACircuitTableViewCell") as! ACircuitTableViewCell
        cell.tableView = self.aTableView
        self.workouts = cell.workouts
        print(workouts.count, " VC workouts array count")
        return cell

    //Setting layout for circuit cells
    default:
        let cell = aTableView.dequeueReusableCell(withIdentifier: "ATableViewCell") as! ATableViewCell
        cell.aLabel.text = workouts[indexPath.row].getName()
        cell.aDetail.text = "Tap here to configure"
        return cell

    }
}

Это мой ACircuitTableViewCell:

class ACircuitTableViewCell: UITableViewCell {

//MARK: Properties
@IBOutlet weak var circuitNumber: UILabel!
@IBOutlet weak var circuitLabel: UILabel!
@IBOutlet weak var circStepper: UIStepper!


var tableView: UITableView!
// var updateCallback : ((_ updateList: Bool)-> Void)?

//var exercises: [Exercise]?
var anArray: [Exercise] = []
var workouts: [Exercise] = [Exercise(name: "Circuit 1", timeMinutes: 2)]

var workoutsCount: Int = 1
var indexPath: NSIndexPath = NSIndexPath(row: 0, section: 1)
//MARK: Original Functions
override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code

    circuitNumber.text = String(workouts.count)
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)
}

@IBAction func valueChanged(_ sender: AnyObject) {
    print("Method .valueChanged activated")

    //Update circuitNumber label
    circuitNumber.text = String(Int(circStepper.value))

    //View pre-array-update status of variables
    print(workouts.count, "anArray before appending")
    print(circStepper.value, "stepper value before appending")
    print(circuitNumber.text, "circuitNumber")

    //Update workouts array
    if workouts.count < Int(circStepper.value) {
        workouts.append(Exercise(name: "Circuit \(Int(circStepper.value))", timeMinutes: 2))
        print(workouts.count, "after appending")

        tableView.reloadData()

       print(workouts.count, "new workout.count")
    }


    print(workouts.count, "workouts.count")
    print("Method .valueChanged completed")

}

Это вывод на консоль с момента загрузки приложения до трех нажатий на кнопку Stepper +.

1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1 number of rows in section 1
1 number of rows in section 0
1  VC workouts array count
Method .valueChanged activated
1 anArray before appending
2.0 stepper value before appending
Optional("2") circuitNumber
2 after appending
1 number of rows in section 1
1 number of rows in section 0
2 new workout.count
2 workouts.count
Method .valueChanged completed
2  VC workouts array count
Method .valueChanged activated
2 anArray before appending
3.0 stepper value before appending
Optional("3") circuitNumber
3 after appending
2 number of rows in section 1
1 number of rows in section 0
3 new workout.count
3 workouts.count
Method .valueChanged completed
3  VC workouts array count
Method .valueChanged activated
3 anArray before appending
4.0 stepper value before appending
Optional("4") circuitNumber
4 after appending
3 number of rows in section 1
1 number of rows in section 0
4 new workout.count
4 workouts.count
Method .valueChanged completed
4  VC workouts array count
Method .valueChanged activated
4 anArray before appending
5.0 stepper value before appending
Optional("5") circuitNumber
5 after appending
4 number of rows in section 1
1 number of rows in section 0
5 new workout.count
5 workouts.count
Method .valueChanged completed
5  VC workouts array count

person Sonera    schedule 18.10.2016    source источник
comment
Пожалуйста, не храните источник данных в своих ячейках (или любых других представлениях). Это нарушает шаблон MVC. Что вам нужно сделать, так это обработать обратный вызов шагового двигателя в контроллере и изменить там источник данных viewController.   -  person alexburtnik    schedule 18.10.2016
comment
@alexburtnik, спасибо! Как только я понял, как обрабатывать обратный вызов шагового двигателя в контроллере, таблица заработала так, как я хотел.   -  person Sonera    schedule 19.10.2016
comment
Пожалуйста. Только что опубликовал два распространенных подхода к обработке событий просмотра в viewController. Вы, вероятно, использовали один из них   -  person alexburtnik    schedule 19.10.2016


Ответы (1)


Вы должны обработать обратный вызов шагового двигателя в контроллере и изменить там источник данных viewController.

  1. Наиболее распространенный способ обработки событий ячейки в контроллере представления — использование делегатов, как я описал здесь: https://stackoverflow.com/a/40111943/1689376

  2. В качестве альтернативы вы можете добавить действие с целью self прямо в методе cellForRow:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
    cell.stepper?.tag = indexPath.row
    cell.stepper?.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged)
    return cell
}

func stepperValueChanged(_ stepper: UIStepper) {
    //use stepper.tag as index to fetch an object from your dataSource
    let workout = dataSource[stepper.tag]
}
person alexburtnik    schedule 19.10.2016