iOS Combine Framework - Издатель публикует только один раз, а потом никогда - PullRequest
1 голос
/ 20 марта 2020

Я пытаюсь использовать комбинацию iOS 13 Combine в сочетании с некоторыми элементами управления UIKit. Я хочу настроить viewcontroller, который содержит переключатель, который включает / отключает кнопку всякий раз, когда переключатель включен / выключен. Согласно документации Apple, элементы управления UIKit имеют встроенную поддержку для издателей Combine и т. Д. c. так что это должно быть возможно.

У меня есть viewcontroller, который содержит UISwitch и UIButton, как показано здесь:

ссылка на скриншот моего viewcontroller

и вот мой код:

import Combine
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var mySwitch: UISwitch!
    @IBOutlet weak var myButton: UIButton!

    var myCancellable: AnyCancellable?

    override func viewDidLoad() {
        super.viewDidLoad()

        mySwitch.isOn = true // Set initial state of switch

        myButton.setTitle("Enabled", for: .normal)
        myButton.setTitle("Disabled", for: .disabled)

        myCancellable = mySwitch.publisher(for: \.isOn)
                                .subscribe(on: RunLoop.main)
                                .assign(to: \.isEnabled, on: myButton)
    }
}

Приведенный выше код должен (или я так думал) генерировать значение свойства .isOn коммутатора при каждом изменении этого свойства и присваивать значение кнопке .isEnabled собственность. Если он работает так, как я ожидал, это означает, что при включении переключателя заголовок кнопки должен иметь значение «Включено», а кнопка должна быть включена. Когда переключатель UIS выключен, тогда название кнопки должно быть «Отключено», а кнопка должна быть отключена.

Но это не так, как я ожидаю. Значение от издателя коммутатора выдается только один раз, когда издатель впервые настроен внутри viewDidLoad(). При нажатии на переключатель, чтобы включить или выключить его, он никогда не выдаст значение снова. Я могу сказать, что, по крайней мере, он выдает значение один раз, потому что, если я изменяю исходное состояние переключателя на «включено» или «выключено», кнопка устанавливается в ожидаемое состояние при загрузке контроллера вида.

Обычно вы Предполагается, что он должен строго ссылаться на издателя, иначе издатель / подписчик будет немедленно прекращен, поэтому я держу ссылку с переменной myCancellable. Но это не решает проблему, значения по-прежнему не выдаются при нажатии на переключатель.

У кого-нибудь есть идеи, как это исправить? Кажется, это должен быть простой пример типа «Hello World» с использованием Combine, и я не знаю, чего мне здесь не хватает.

1 Ответ

1 голос
/ 21 марта 2020

Распространенная ошибка - думать, что свойство UISwitch isOn соответствует KVO. К сожалению, это не так. Вы не можете использовать publisher(for:) для его наблюдения.

Создайте @IBAction в вашем ViewController и подключите к нему событие Value Changed коммутатора.

...