Combine-实践

2020-05-18 23:10:21 浏览数 (1)

Combine 既可以在 SwiftUI 中使用,也可以在 UIKit 中使用。下面分别实践一下。

SwiftUI

声明式UI 响应式编程是未来移动开发的趋势,所以 Combine 对于 SwiftUI 来说是不可或缺的一部分,这也是为什么 Combine 会随着 SwiftUI 一起发布。在 SwiftUI 中任何一个 View 都可以作为 Subscriber。 SwiftUI 中的 View 协议定义了一个onReceive()的函数可以将 View 变成 Subscriber。onReceive()函数接收一个 Publisher,然后跟上一个类似于sink的闭包,可以在其中操作@State@Binding修饰的属性数据。

代码语言:javascript复制
import SwiftUI

struct ContentView: View {
    
    @State private var currentValue = "?"
    
    var body: some View {
        Text(currentValue)
            .onReceive(Just("SwiftUI   Combine")) { value in
                self.currentValue = value
        }
    }
}  

UIKit

虽然 SwiftUI Combine 是一对黄金搭档,但是在 UIKit 中 Combine 也可以发挥重要作用。如下图的案例,当开关打开(关闭)的时候,按钮可以(不能)点击,点击发送通知按钮,蓝色的标签显示发送的通知内容。

实现效果

代码语言:javascript复制
import UIKit
import Combine

extension Notification.Name{
    static var newMessage = Notification.Name("YungFan")
}

class ViewController: UIViewController {
    
    @IBOutlet weak var allowMessageSwitch: UIButton!
    @IBOutlet weak var sendButton: UIButton!
    @IBOutlet weak var messageLabel: UILabel!
    
    @Published var canSendMessage: Bool = false
    private var cancellables: Set<AnyCancellable> = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // canSendMessage的改变绑定到Button的isEnabled上
        $canSendMessage
            .receive(on: DispatchQueue.main)
            .assign(to: .isEnabled, on: sendButton)
            .store(in: &cancellables)
        
        // 通知需要绑定到messageLabel的text
        NotificationCenter.default.publisher(for: .newMessage)
            .map{ notification -> String in
                notification.object as? String ?? ""
        }
        .assign(to: .text, on: messageLabel)
        .store(in: &cancellables)
        
        /*
         // 上面的写法等于下面3句
        let messagePublisher = NotificationCenter.Publisher(center: .default, name: .newMessage)    
        let messageSubscriber = Subscribers.Assign(object: messageLabel, keyPath: .text)
        messagePublisher
            .map{ notification -> String in
                notification.object as? String ?? ""
        }.subscribe(messageSubscriber)
        */
    }
    
    @IBAction func switchChanged(_ sender: UISwitch) {
        // canSendMessage的改变随开关改变
        self.canSendMessage = sender.isOn
    }
    
    @IBAction func buttonClicked(_ sender: UIButton) {
        // 发送通知
        NotificationCenter.default.post(name: .newMessage, object: "This is the (Int.random(in: 0...100)) message")
    }
}

0 人点赞