iOS 组合框架 - 发布者仅发布一次,然后不再发布

Sha*_*n S 4 reactive-programming ios swift combine

我正在尝试将 iOS 13 组合框架与一些 UIKit 控件结合使用。我想设置一个视图控制器,其中包含一个开关,每当打开/关闭开关时,该开关就会启用/禁用按钮。根据 Apple 的文档,UIKit 控件内置了对合并发布者等的支持,因此这应该是可能的。

我有一个包含 UISwitch 和 UIButton 的视图控制器,如下所示:

链接到我的视图控制器的屏幕截图

这是我的代码:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码应该(或者我认为)每当开关.isOn属性发生变化时发出该属性的值,并将该值分配给按钮的.isEnabled属性。如果它按照我期望的方式运行,这意味着当开关切换为“ON”时,按钮标题应显示“已启用”,并且应启用该按钮。当 UISwitch 关闭时,按钮标题应显示为“Disabled”,并且按钮应被禁用。

但它的行为并不符合我的预期。当首次在 内部设置发布者时,交换机发布者的值仅发出一次viewDidLoad()。当点击开关将其打开或关闭时,它再也不会发出值。我可以告诉它至少发出一次值,因为如果我将开关的初始状态更改为打开或关闭,则加载视图控制器时按钮将设置为预期状态。

通常,您应该保留对发布者的强引用,否则发布者/订阅者将立即终止,因此这就是我持有变量引用的原因myCancellable。但这并不能解决问题,点击开关时仍然不会发出这些值。

有人对如何解决这个问题有任何想法吗?这看起来应该是一个使用组合的简单“Hello World”类型的示例,我不知道我在这里缺少什么。

rob*_*off 7

一个常见的错误是认为 的UISwitch财产isOn符合 KVO 标准。遗憾的是,事实并非如此。你不能publisher(for:)用来观察它。

@IBAction在您的 中创建一个ViewController,并将交换机的 Value Changed 事件连接到它。