Уведомление не работает для UISegmentController

У меня есть табличное представление. Я регистрирую Cell следующим образом:

tableView.register(TVCellElementProperties.self, forCellReuseIdentifier: cellId1)

Внутри TVCellElementProperties я вручную создал контроллер сегмента следующим образом:

    let unitTypeSegmentedControl: UISegmentedControl = {
    let types = ["Blue", "White"]
    let sc = UISegmentedControl(items: types)
    sc.selectedSegmentIndex = 0
    sc.translatesAutoresizingMaskIntoConstraints = false
    sc.tintColor = UIColor.darkBlue
    sc.addTarget(self, action: #selector(handleUnitChange), for: .valueChanged)

    return sc
}()

@objc func handleUnitChange() {
    NotificationCenter.default.post(name: .unitPicked, object: self)
}

Итак, я думаю, что когда я изменяю значение внутри SegmentController, он должен перенаправить меня к функции handleUnitChange()

внутри tableView я вставил эту строку в ViewDidLoad:

NotificationCenter.default.addObserver(self, selector: #selector(unitPicked), name: .unitPicked, object: nil)

Когда я запускаю приложение, функция **handleUnitChange** внутри tableviewCell не вызывается. Что я сделал не так? как я узнаю, что я нажал?

РЕДАКТИРОВАТЬ: я вызываю функцию setupView, которая отвечает за вставку контроллера сегмента внутри ячейки из init внутри UITableViewCell следующим образом:

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.setupViews()
    print("test init")
}

Итак, когда я запускаю его, setupView вызывается только один раз, поэтому ** handleUnitChange ** тоже вызывается только один раз. Я имею в виду, что когда приложение запущено и работает, и когда я нажимаю на контроллер сегмента внутри TableView, функция handleUnitChange больше не вызывается.

Я попытался вызвать функцию из Cell внутри CellForRow, но так же, как и выше. функция ** handleUnitChange ** не вызывается сверхурочно, я щелкнул внутри контроллера сегментов.

if let cell = tableView.dequeueReusableCell(withIdentifier: cellId1, for: indexPath) as? TVCellElementProperties {

    //cell.backgroundColor = UIColor.rgb(red: 12, green: 122, blue: 12)
    //cell.contentView.isUserInteractionEnabled = false
    cell.setupViews()
    //print("\(cell.handleUnitChange(sender: u))")
    cell.handleUnitChange(sender: cell.unitTypeSegmentedControl)
    return cell
}

person Xin Lok    schedule 20.02.2018    source источник
comment
@objc func handleUnitChange (отправитель: UISegmentedControl) { print (sender.selectedSegmentIndex)}   -  person El Tomato    schedule 20.02.2018
comment
Вам не нужно ничего помещать в ViewDidLoad. Возможно, вам придется инициировать действие с закрытием внутри tableViewCell.   -  person El Tomato    schedule 20.02.2018
comment
Можете ли вы опубликовать код, который вы делаете в своей камере?   -  person Agent Smith    schedule 20.02.2018
comment
проверьте, работает ли какое-либо из приведенных здесь решений или нет? stackoverflow.com/ вопросы/18848689/   -  person Vincent Joy    schedule 20.02.2018
comment
@El Tomato: я пробовал, но все равно не читал функцию handleUnitChange внутри tableViewCell.   -  person Xin Lok    schedule 20.02.2018
comment
@Agent Smith: Внутри ячейки я вызываю функцию настройки из tableViewCell, чтобы просто добавить к ней SegmentController с его ограничениями.   -  person Xin Lok    schedule 20.02.2018
comment
Как я уже предлагал ранее, используйте замыкание.   -  person El Tomato    schedule 21.02.2018
comment
Вам все еще нужна помощь?   -  person El Tomato    schedule 21.02.2018
comment
@El Tomato: я ИЗМЕНЯЮ вопрос, чтобы сделать его более понятным, функция handleUnitChange вызывается только один раз, когда я запускаю приложение. Мне не хватает чего-то, что я не могу найти сам.   -  person Xin Lok    schedule 21.02.2018
comment
@El Tomato: То, что я написал внутри CellForRow, верно? это правильный способ получить информацию из TableViewCell?   -  person Xin Lok    schedule 21.02.2018
comment
Нет. Извините, но для меня это не имеет смысла.   -  person El Tomato    schedule 21.02.2018
comment
@ElTomato Итак, как получить значение из tableViewCell?   -  person Xin Lok    schedule 21.02.2018


Ответы (1)


Шаг 1

Сначала мы работаем над UITableViewCell.

class ProfileTableViewCell: UITableViewCell {
    // MARK: - IBOutlet
    @IBOutlet var firstLabel: UILabel!
    @IBOutlet var lastLabel: UILabel!
    @IBOutlet var ageLabel: UILabel!
    @IBOutlet var pictureImageView: UIImageView!
    @IBOutlet weak var segmentControl: UISegmentedControl! // (a)

    // MARK: - awakeFromNib
    override func awakeFromNib() {
        super.awakeFromNib()
        firstLabel.backgroundColor = UIColor.clear
        lastLabel.backgroundColor = UIColor.clear
        ageLabel.backgroundColor = UIColor.clear
        segmentControl.addTarget(self, action: #selector(valueChanged), for: .valueChanged) // (b)
    }

    var onSegmentChanged: ((Int, Int) -> Void)? // (c)

    // (d)
    @objc func valueChanged(sender: UISegmentedControl) {
        onSegmentChanged!(sender.tag, sender.selectedSegmentIndex)
    }
}

Во-первых, добавьте соединение IBOutlet (a) через Interface Builder. Установите цель селектора (b) через awakFromNib. Чтобы получить действие пользователя через UITableView, вы должны отправить сигнал с замыканием (c). Наконец, добавьте целевой приемник (c).

Шаг 2

Теперь мы работаем с UIViewController.

class HomeViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard let people = fetchedResultsController.fetchedObjects else { return 0 }
        return people.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ProfileTableViewCell
        let person = fetchedResultsController.object(at: indexPath)
        cell.segmentControl.tag = indexPath.row // (e)
        // action //
        (f)
        cell.onSegmentChanged = { tag, selectedSegment in
            // (g) self.segmentTapped(tag: tag, index: selectedSegment)
            // print(tag, selectedSegment)
        }
        return cell
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            // fetching data //
            let person = fetchedResultsController.object(at: indexPath)

            // deleting data //
            person.managedObjectContext?.delete(person)

            // saving the change //
            let context = persistentContainer.viewContext
            do {
                try context.save()
                print("saved...")
            } catch {
                print("failed saving")
            }
        }
    }

    (h)
    func segmentTapped(tag: Int, index: Int) {
        print(tag, index)
    }
}

Когда вы отправляете действие пользователя через UITableViewCell, вы должны получить его через UIViewController с помощью метода делегата cellForRowAt UITableView. Чтобы увидеть, какой элемент управления сегмента выбрал пользователь, вы устанавливаете тег (e). Замыкание (f) устанавливается перед возвратом cell. Вы можете распечатать результат внутри замыкания. Если вы хотите получить результат из метода делегата, см. (g) и (h).

Предупреждение

Если вы внимательно посмотрите на строку (e), то увидите, что indexPath.row используется как тег. Этот подход работает, только если вы знаете, что ни одна из строк таблицы не удаляется. В противном случае данные вашей таблицы должны иметь значение словаря, которое дает каждой строке уникальный номер.

Тест

Посмотри, как это работает. Когда пользователь использует элемент управления сегментом во второй строке, вы получите вызов через cellForRowAt. Результат 2 и 1, 2 как в строке, 1 как в значении selectedSegmentIndex. Пользователю не нужно выбирать какие-либо строки таблицы.

введите здесь описание изображения

person El Tomato    schedule 21.02.2018
comment
Отличное объяснение. Большое спасибо - person Xin Lok; 22.02.2018