首页 > 其他分享 >Swift中发布-订阅框架Combine的使用

Swift中发布-订阅框架Combine的使用

时间:2023-09-21 20:58:16浏览次数:34  
标签:Publisher 订阅 Subscriber let 数据流 Combine Swift

Combine简介 Combine是一个苹果用来处理事件的新的响应式框架,支持iOS 13及以上版本。 你可以使用Combine去统一和简化在处理类似于target-action,delegate,kvo等事情的代码。 iOS目前已经有第三方的响应式框架了,如:RxSwift、ReactiveCocoa,但是苹果现在发布了自己的新的框架。 它提供了一种声明式、函数式的编程方式,可以让开发者更加简单、高效地处理异步数据流。
Combine核心概念
Combine的核心概念是Publisher、Subscriber和Operator。发布者,订阅者和中间操作者。 发布者Publisher:可以将值或错误发送给订阅者,并且在完成或取消时,向订阅者发送相应的消息。 订阅者Subscriber:接收发布者发送的值、错误和完成信息,并进行相应的处理。 操作符Operator:用来对数据流进行转换、过滤、合并等处理,Combine框架中提供了很多操作符,例如map、filter、merge等。
当一个Publisher发布一个事件时,Subscriber会被通知这个事件,并执行相应的操作。 一个Subscriber可以订阅多个Publisher,并且每个Publisher都可以同时拥有多个Subscriber。当所有的Subscriber都取消订阅时,Publisher会停止发布事件。 Operator可以对事件流进行各种操作,包括数据转换、过滤、组合等。比如,map操作可以将一个事件流中的元素转换成另一个类型,filter操作可以过滤出符合条件的元素,merge操作可以将多个事件流合并成一个事件流等。   map操作符可以将数据流中的值进行转换,返回一个新的数据流。例如,将一个字符串转换成大写形式:

let stringPublisher = Just("hello, world!")
let uppercasedPublisher = stringPublisher.map { $0.uppercased() }
filter对数据流中的值进行过滤,返回一个新的数据流。例如,过滤掉数组中的偶数:
let arrayPublisher = [1, 2, 3, 4, 5].publisher
let oddPublisher = arrayPublisher.filter { $0 % 2 != 0 }
merge对数据流进行合并,生成一个数据流。例如,将两个发布者合并成一个:
let publisher1 = Just("hello")
let publisher2 = Just("world")
let mergedPublisher = Publishers.Merge(publisher1, publisher2)
下面是一个简单的例子,展示了如何使用Combine来监听一个UITextField的文本输入
import UIKit
import Combine

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    var cancellables = Set<AnyCancellable>()

    override func viewDidLoad() {
        super.viewDidLoad()

        // 创建一个订阅者,打印出文本输入的内容
        let subscriber = Subscribers.Assign(object: self.textField, keyPath: \.text)

        // 订阅文本输入框的文本变化事件
        self.textField.textPublisher(for: .editingChanged)
            .map { $0.text ?? "" }
            .subscribe(subscriber)
            .store(in: &cancellables)
    }
}

extension UITextField {
    func textPublisher() -> AnyPublisher<String, Never>
    {
        NotificationCenter.default
            .publisher(for: UITextField.textDidChangeNotification, object: self)
            .map {($0.object as? UITextField)?.text  ?? ""}
            .eraseToAnyPublisher()
    }
}

 

AnyCancellable Combine 中还定义了一个 AnyCancellable 类,实现了 Cancellable 协议,特点是会在该类析构时自动执行 cancel 方法。
在实际开发中,当 Subscriber 在某个时候不想接收 Publisher 发布的数据时,可以取消订阅以释放资源。 Combine 中提供了 Cancellable 协议,该协议中定义了一个 cancel 方法,用于取消订阅流程。
import Combine
let subject = PassthroughSubject<String, Never>() // 创建PassthroughSubject
// 订阅
let subscription = subject.sink(receiveCompletion: { _ in
    print("receiveCompletion")
}, receiveValue: { value in
    print(value)
    
})
// 发送数据
subject.send("hello")
// 中途取消订阅
subscription.cancel()
// 后面发送的数据都会失败
subject.send("world")
subject.send(completion: .finished)
/* 输出:
 hello
 */
可以理解为 AnyCancellable是一种管理订阅状态的工具,能根据开发者需要在某个时段切断 Publisher和 Subscriber的联系。 AnyCancellable 的一个应用就是可以在某种情况下中断网络请求,实现如下:
import UIKit
import Combine
let dataPublisher = URLSession.shared.dataTaskPublisher(for: URL(string: "https://louyu.cc")!)
let cancellableSink = dataPublisher.sink { completion in
    switch completion {
    case .finished:
        break
    case .failure(let error):
        print("error: \(error)")
        break
    }
} receiveValue: { value in
    print("received \(value)")
}
cancellableSink.cancel() //取消网络请求

参考文章地址: https://www.jianshu.com/p/1dc27229a533 https://louyu.cc/articles/ios-swift/2021/03/?p=2865/  

标签:Publisher,订阅,Subscriber,let,数据流,Combine,Swift
From: https://www.cnblogs.com/zhou--fei/p/17720908.html

相关文章

  • 基于微信平台的报刊订阅小程序
    计算机网络发展到现在已经好几十年了,在理论上面已经有了很丰富的基础,并且在现实生活中也到处都在使用,可以说,经过几十年的发展,互联网技术已经把地域信息的隔阂给消除了,让整个世界都可以即时通话和联系,极大的方便了人们的生活。所以说,基于微信平台的报刊订阅小程序用计算机技术来进行......
  • iOS开发Swift-回调函数
    回调函数:回调函数是一种将函数作为参数传递给另一函数的策略。当特定事件或条件发生时,传递的函数(即回调函数)将被调用。这种机制允许在事件发生时执行自定义的代码,因此它是异步编程的重要组成部分。在Swift中,可以使用闭包(closure)或函数作为回调函数。假设你有一个函数叫做greet(......
  • iOS开发Swift-??
    letg=F(a:s??0.0,b:l??0.0,c:d??0.0)这段代码在创建一个名为g的F对象。F是一个自定义类,它的实例化对象包含一些目标值,如a、b和c。这些目标值通过可选链操作符(??)设置,如果对应的变量为空(nil),那么就会使用默认值0.0。 ??是可选链操作符(nil-coalescingoperato......
  • 一文告诉你为什么时序场景下 TDengine 数据订阅比 Kafka 好
    在TDengine3.0中,我们对流式计算、数据订阅功能都进行了再升级,帮助用户极大简化了数据架构的复杂程度,降低整体运维成本。TDengine提供的类似消息队列产品的数据订阅、消费接口,本质上是为了帮助应用实时获取写入TDengine的数据,或者以事件到达顺序处理数据,与其他消息队列相比,它......
  • iOS开发Swift-alertWithTitle(title: xxx, message: xxx, placeHolders: xxx, buttons
    alertWithTitle(title:"输入信息",message:"请输入您的姓名:",placeHolders:[],buttons:["确定"],defaultButtonIndex:0,cancelButtonIndex:0,defaultText:"张三");当调用这个函数时,会弹出一个带有标题"输入信息"和消息"请输入您的姓名:"的对话框,......
  • iOS开发Swift-UITableView-navigationController?.pushViewController(fileOperation,
    navigationController?.pushViewController(fileOperation,animated:true) 通过导航控制器(navigationController)将一个新的视图控制器(fileOperation)推入栈顶,同时以动画的形式展示这个过程。如果navigationController为nil,那么pushViewController操作将不会执行。在iOS开发......
  • iOS开发Swift-as,as!,as?
    as是强制类型转换运算符。使用它可以将一个对象的类型转换为另一种类型。如果类型转换失败,会触发一个运行时错误。as!是强制类型转换运算符。使用它可以将一个对象的类型转换为另一种类型。如果类型转换失败,会触发一个运行时错误。它与as类似,但是它更加强烈地说明了类型转换是......
  • iOS开发Swift-UITableView-func tableView(_ tableView: UITableView, cellForRowAt i
    functableView(_tableView:UITableView,cellForRowAtindexPath:IndexPath)->UITableViewCell{letcellid="testCellID"//cell的IDvarcell=tableView.dequeueReusableCell(withIdentifier:cellid)//对cell赋值ifcel......
  • iOS开发Swift-UITableView-func tableView(_ tableView: UITableView, numberOfRowsIn
    functableView(_tableView:UITableView,numberOfRowsInSectionsection:Int)->Int{return6}返回一个整形.作用:UITableView的DataSource,用来确定cell的个数.numberOfRowsInSection就是在界面中的行数例如: ......
  • Canal实现MySQL增量数据的订阅和消费
    介绍canal,译意为水道/管道/沟渠,主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费。canal的工作原理就是把自己伪装成MySQLslave,模拟MySQLslave的交互协议向MySQLMaster发送dump协议,MySQLmater收到canal发送过来的dump请求,开始推送binarylog给canal,然后ca......