ios - iOS 组合框架 - 发布者只发布一次,然后再也不发布
问题描述
我正在尝试将 iOS 13 Combine 框架与一些 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)
}
}
上面的代码应该(或者我认为).isOn
在该属性更改时发出开关属性的值,并将该值分配给按钮的.isEnabled
属性。如果它以我期望的方式运行,这意味着当开关切换为 ON 时,按钮标题应显示为“已启用”,并且应启用该按钮。当 UISwitch 切换为 OFF 时,按钮标题应显示为“已禁用”并且该按钮应被禁用。
但它的行为并不符合我的预期。当发布者第一次在内部设置时,来自开关的发布者的值只会发出一次viewDidLoad()
。当点击开关打开或关闭它时,它永远不会再发出一个值。我可以说它至少发出一次值,因为如果我将开关的初始状态更改为打开或关闭,则在加载视图控制器时按钮将设置为预期状态。
通常,您应该保持对发布者的强引用,否则发布者/订阅者将立即终止,这就是我持有myCancellable
变量引用的原因。但这并不能解决问题,点击开关时仍然不会发出值。
有没有人对如何解决这个问题有任何想法?这似乎应该是一个使用组合的简单“Hello World”类型的示例,我不知道我在这里缺少什么。
解决方案
一个常见的错误是认为UISwitch
' 的isOn
属性是 KVO 兼容的。可悲的是,事实并非如此。你不能publisher(for:)
用来观察它。
@IBAction
在您的 中创建一个ViewController
,并将开关的 Value Changed 事件连接到它。
推荐阅读
- image - Blogger 网站中的新图像分辨率问题
- ios - 为 Xcode 11 执行“carthage update”时获取“[NSRunLoop addPort:forMode:]: port argument cannot be nil'”
- node.js - 将新文档保存在另一个集合中后,是否可以在回调函数中更新文档?
- java - Cloud Firestore 添加文档的问题 - Android Studio
- android - 浮动操作按钮 (Fab) 迁移到 sdk 28 后的图标大小问题
- java - 已经有 ID 的 POJO (java.lang.Long)
- asp.net-mvc - 尝试编写存储过程并将结果绑定到表中的视图中
- ruby-on-rails - 在一个 POST 请求中创建多个 ActiveRecord 对象时的最佳做法是什么
- google-apps-script - Google Apps 脚本 - 根据属性服务中的用户设置添加不同的菜单项?
- email - 无法让@TeamHive/capacitor-email 在 Ionic 4 中工作