使用 Combine 接收和处理事件

自定义和接收来自异步源的事件。

 

接下来将使用一个简单的实例来讲述如何使用Combine接收和处理事件。

 

假设您的应用中需要根据一个文本值实时更新列表内容,例如根据关键字进行搜索,那么在文字实时变化的过程中,AppKit会同时发送通知Notification以供订阅。

 

使用订阅者订阅

步骤一:使用NotificationCenter提供的方法publisher(for:object:)生成一个发布者


let pub = NotificationCenter.default

    .publisher(for: NSControl.textDidChangeNotification, object: filterField)

 

步骤二:系统提供了2个内置订阅者,可供使用

  • sink(receiveCompletion:receiveValue:)中的2个闭包回调,第一个闭包接收Subscribers.Completion枚举类型标识当前是状态是成功还是失败,第二闭包接收结果值。

  • assign(to:on:)立即将它接收到的每个元素分配给给定对象的属性,使用键路径(key path)来指示属性。


let sub = NotificationCenter.default

    .publisher(for: NSControl.textDidChangeNotification, object: filterField)

    .sink(receiveCompletion: { print ($0) },

          receiveValue: { print ($0) })

 

使用运算符更改输出类型

步骤三:使用map(_:)运算符转换为不同类型,首先将Notificationobject属性转换为NSTextField,再取得其字符值


let sub = NotificationCenter.default

    .publisher(for: NSControl.textDidChangeNotification, object: filterField)

    .map( { ($0.object as! NSTextField).stringValue } )

    .sink(receiveCompletion: { print ($0) },

          receiveValue: { print ($0) })

 

同样的,您也可以使用assign(to:on:),如下将最后的值赋予了myViewModel的属性filterString


let sub = NotificationCenter.default

    .publisher(for: NSControl.textDidChangeNotification, object: filterField)

    .map( { ($0.object as! NSTextField).stringValue } )

    .assign(to: \MyViewModel.filterString, on: myViewModel)

 

使用运算符自定义发布者

使用运算符来改进此事件处理链的三种方法

  • 使用filter(_:)运算符忽略特定长度以下的输入或拒绝非字母数字字符

  • 使用debounce(for:scheduler:options:)运算符指定事件发送最短时间间隔

  • 使用receive(on:options:)用于将回调传递给主线程更新UI

 

步骤四:使用运算符完善发布流程


let sub = NotificationCenter.default

    .publisher(for: NSControl.textDidChangeNotification, object: filterField)

    .map( { ($0.object as! NSTextField).stringValue } )

    .filter( { $0.unicodeScalars.allSatisfy({CharacterSet.alphanumerics.contains($0)}) } )

    .debounce(for: .milliseconds(500), scheduler: RunLoop.main)

    .receive(on: RunLoop.main)

    .assign(to:\MyViewModel.filterString, on: myViewModel)

 

取消发布

 

sink(receiveCompletion:receiveValue:)assign(to:on:)实现了Cancellable协议,如果您需要取消发布,只需要调用:


sub?.cancel()

Made with in Shangrao,China By 老雷

Copyright © devler.cn 1987 - Present

赣ICP备19009883号-1