4

如何扩展 Combine:以给 UIButton 设置 title 为例

 3 years ago
source link: https://imtx.me/blog/how-to-extend-combine-set-title-for-uibutton/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何扩展 Combine:以给 UIButton 设置 title 为例

我的 PasteNow 用了 Apple 自带的 Combine 库来实现一些响应式的设计,因为之前有 RxSwift 的使用经验,因此上手 Combine 比较快,加上是系统自带的,用起来也非常顺手。于是我最近还在做另外一件事情:迁移其他旧项目的 RxSwift 代码至 Combine。因为 Combine 作为 iOS 13/macOS 10.15 就引入的系统库,现在已经到了可以普遍采用的程度了,是时候和 RxSwift 说再见了。

毕竟 RxSwift 发展了那么多年,生态还是比 Combine 要丰富一些。于是在从 RxSwift 迁移至 Combine 的过程中,我遇到了不少 RxSwift 可以非常方便做到的事情,但在 Combine 默认不太方便。好在我们可以去扩展 Combine,就让我用一个 UIButton 设置 title 的例子来说明这个吧。

比如 RxSwift 里可以非常方便地将一个值绑定到 UIButton 上去:

.bind(to: button.rx.title(for: .normal))

在 Combine 里面,就只能:

.sink(receiveValue: { title in
        button.setTitle(title, for: .normal)
})

如果这个 button 还是 self 上的,那么还得麻烦来一个 weak self,不然会强引用。

.sink(receiveValue: { [weak self] title in
        self?.button.setTitle(title, for: .normal)
})

真的是非常麻烦呢。但只需要写这样的一个扩展,就能轻松解决这个问题:

import UIKit
import Combine

extension Publisher where Self.Output == String, Self.Failure == Never {

    public func setTitle(on button: UIButton, state: UIControl.State) -> AnyCancellable {
        sink { title in
            button.setTitle(title, for: state)
        }
    }

}

然后就可以快乐地这样调用了:

.setTitle(on: button, state: .normal)

希望这则小技巧可以帮助到你,欢迎交流讨论。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK