简体   繁体   English

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

[英]iOS Combine Framework - Publisher Only Publishes Once and Then Never Again

I am trying to use the iOS 13 Combine framework in conjunction with some UIKit controls.我正在尝试将 iOS 13 Combine 框架与一些 UIKit 控件结合使用。 I want to set up a viewcontroller that contains a switch that enables/disables a button whenever the switch is toggled on/off.我想设置一个包含一个开关的视图控制器,该开关在开关打开/关闭时启用/禁用按钮。 According to Apple's documentation, UIKit controls have built-in support for Combine publishers, etc. so this should be possible.根据 Apple 的文档,UIKit 控件内置了对 Combine 发布者等的支持,所以这应该是可能的。

I have a viewcontroller that contains a UISwitch and a UIButton, as shown here:我有一个包含 UISwitch 和 UIButton 的视图控制器,如下所示:

link to screenshot of my viewcontroller链接到我的视图控制器的屏幕截图

and here is my code:这是我的代码:

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)
    }
}

The above code should (or so I thought) emit the value of the switch's .isOn property, whenever that property changes, and assign the value to the button's .isEnabled property.上面的代码应该(或者我认为)发出开关的.isOn属性的值,每当该属性更改时,并将该值分配给按钮的.isEnabled属性。 If it is running the way I would expect, that means that when the switch is toggled ON the button title should read "Enabled" and the button should be enabled.如果它以我期望的方式运行,这意味着当开关切换为 ON 时,按钮标题应显示为“已启用”,并且应启用该按钮。 When the UISwitch is toggled OFF, then the button title should read "Disabled" and the button should be disabled.当 UISwitch 切换为 OFF 时,按钮标题应显示为“已禁用”并且按钮应被禁用。

But it does not behave the way I am expecting.但它的行为并不像我期望的那样。 The value from the switch's publisher is only emitted once, when the publisher is first set up inside viewDidLoad() .当第一次在viewDidLoad()设置发布者时,来自 switch 发布者的值只发出一次。 When tapping on the switch to toggle it on or off, it never emits a value ever again.当点击开关打开或关闭它时,它永远不会再发出一个值。 I can tell it is at least emitting the value once, because if I change the initial state of the switch to either on or off, the button is set to the expected state when the viewcontroller is loaded.我可以告诉它至少发出一次值,因为如果我将开关的初始状态更改为打开或关闭,则在加载视图控制器时按钮将设置为预期状态。

Typically you are supposed to keep a strong reference to the publisher, or else the publisher/subscriber will be terminated immediately, so that's why I am holding a reference with the myCancellable variable.通常,您应该保留对发布者的强引用,否则发布者/订阅者将立即终止,这就是为什么我使用myCancellable变量持有引用的myCancellable But this does not fix the issue, the values are still not emitted when tapping on the switch.但这并不能解决问题,点击开关时仍然没有发出值。

Does anyone have any ideas on how to fix this?有没有人对如何解决这个问题有任何想法? This seems like it should be a simple "Hello World" type of example using Combine, and I don't know what I am missing here.这似乎应该是一个简单的“Hello World”类型的使用 Combine 的例子,我不知道我在这里遗漏了什么。

A common mistake is thinking that UISwitch 's isOn property is KVO-compliant.一个常见的错误是认为UISwitchisOn属性是 KVO 兼容的。 Sadly, it isn't.可悲的是,事实并非如此。 You cannot use publisher(for:) to observe it.您不能使用publisher(for:)来观察它。

Create an @IBAction in your ViewController , and connect the switch's Value Changed event to it.在您的ViewController创建一个@IBAction ,并将开关的 Value Changed 事件连接到它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 合并 Publisher 只执行一次.sink 操作 - Combine Publisher performs .sink action only once 使用 iOS 中的组合框架根据值向发布者添加延迟 - Add delay to publisher based on value with Combine Framework in iOS iOS 13 仅在用户“允许一次”后再次调用 requestAlwaysAuthorization - iOS 13 call requestAlwaysAuthorization again after user “Allow Once” only iOS - 合并 - 将发布者类型更改为子类型 - iOS - Combine - Change Publisher type to child type iOS Swift 组合:使用单个值发出发布者 - iOS Swift Combine: Emit Publisher with single value 如何使scollView(用于T&C)仅在应用程序开始时显示一次,然后再也不显示? - How to make scollView (for T&C) only show up once at begin of app, then never show up again? 加载保存到文档目录中的图像只能进行一次,然后再也不会加载 - Loading an image saved to the Documents Directory only works once, then never loads again NSNetService发布,但didAcceptConnectionWithInputStream…从未被调用 - NSNetService publishes, but didAcceptConnectionWithInputStream… is never called send() 仅在组合框架 iOS 中第一次被调用 - send() gets called only for the first time in combine framework iOS Swift 组合错误:'Publisher' 上的方法 requires.Failure'(又名'WeatherError')和'Never' 是等效的 - Swift combine error: method on 'Publisher' requires .Failure' (aka 'WeatherError') and 'Never' be equivalent
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM