有没有办法使用 Combine 的 .assign 而不是 .sink 来更新 UIButton 的 titleLabel 文本?
Is there a way to update UIButton's titleLabel text using Combine's .assign instead of .sink?
我的视图模型中有一个 @Published
字符串。我想在我的视图控制器中接收其值的更新,以便我可以更新 UI.
我能够通过使用 sink
订阅者成功获取更新。这很好用:
viewModel.$buttonText.sink { [weak self] buttonText in
self?.buttonOutlet.setTitle(buttonText, for: .normal)
}.store(in: &cancellables)
但我正在寻找一种单线方法。更像是您可以使用 assign
订阅者对 UI 标签执行的操作:
viewModel.$title.assign(to: \.text, on: titleLabel).store(in: &cancellables)
我试过直接访问 buttonOutlet.titleLabel
,但这当然行不通,因为我们不能直接更新文本(UIButton.titleLabel
是只读的)。它还引入了展开 titleLabel
属性:
的问题
viewModel.$buttonText.assign(to: \.!.text, on: buttonOutlet.titleLabel).store(in: &cancellables)
我不知道我是否只是在努力寻找正确的语法,或者这是否只是目前 Combine 的一个限制。
你可以写一个扩展:
extension UIButton {
var normalTitleText: String? {
get {
title(for: .normal)
}
set {
setTitle(newValue, for: .normal)
}
}
}
现在你可以得到keypath
viewModel.$title.assign(to: \.normalTitleText, on: someButton).store(in: &cancellables)
另一个选项:
extension UIButton {
func title(for state: UIControl.State) -> (String?) -> Void {
{ title in
self.setTitle(title, for: state)
}
}
}
因此您不必为每个控件状态编写不同的var
。可以这样使用:
viewModel.$buttonText
.sink(receiveValue: buttonOutlet.title(for: .normal))
.store(in: &cancellables)
其他答案没有错,但如果您只想要最少的代码,可以通过直接捕获 buttonOutlet
并使用 [=12=]
作为闭包参数来收紧代码。
viewModel.$buttonText
.sink { [b = buttonOutlet] in b?.setTitle([=10=], for: .normal) }
.store(in: &cancellables)
我的视图模型中有一个 @Published
字符串。我想在我的视图控制器中接收其值的更新,以便我可以更新 UI.
我能够通过使用 sink
订阅者成功获取更新。这很好用:
viewModel.$buttonText.sink { [weak self] buttonText in
self?.buttonOutlet.setTitle(buttonText, for: .normal)
}.store(in: &cancellables)
但我正在寻找一种单线方法。更像是您可以使用 assign
订阅者对 UI 标签执行的操作:
viewModel.$title.assign(to: \.text, on: titleLabel).store(in: &cancellables)
我试过直接访问 buttonOutlet.titleLabel
,但这当然行不通,因为我们不能直接更新文本(UIButton.titleLabel
是只读的)。它还引入了展开 titleLabel
属性:
viewModel.$buttonText.assign(to: \.!.text, on: buttonOutlet.titleLabel).store(in: &cancellables)
我不知道我是否只是在努力寻找正确的语法,或者这是否只是目前 Combine 的一个限制。
你可以写一个扩展:
extension UIButton {
var normalTitleText: String? {
get {
title(for: .normal)
}
set {
setTitle(newValue, for: .normal)
}
}
}
现在你可以得到keypath
viewModel.$title.assign(to: \.normalTitleText, on: someButton).store(in: &cancellables)
另一个选项:
extension UIButton {
func title(for state: UIControl.State) -> (String?) -> Void {
{ title in
self.setTitle(title, for: state)
}
}
}
因此您不必为每个控件状态编写不同的var
。可以这样使用:
viewModel.$buttonText
.sink(receiveValue: buttonOutlet.title(for: .normal))
.store(in: &cancellables)
其他答案没有错,但如果您只想要最少的代码,可以通过直接捕获 buttonOutlet
并使用 [=12=]
作为闭包参数来收紧代码。
viewModel.$buttonText
.sink { [b = buttonOutlet] in b?.setTitle([=10=], for: .normal) }
.store(in: &cancellables)