如何在SwiftUI中接收通知中心帖子

如何在SwiftUI中接收通知中心帖子,swiftui,publish-subscribe,combine,Swiftui,Publish Subscribe,Combine,我已经看过十几本关于如何使用Combine并接收任务完成通知的教程。似乎它们都显示线性代码——发布者和接收者都在同一个位置,一行接一行 发布通知非常简单,如下代码所示: // background download task complete - notify the appropriate views DispatchQueue.main.async { NotificationCenter.default.post(name: .dataDownloadComplete, objec

我已经看过十几本关于如何使用Combine并接收任务完成通知的教程。似乎它们都显示线性代码——发布者和接收者都在同一个位置,一行接一行

发布通知非常简单,如下代码所示:

// background download task complete - notify the appropriate views
DispatchQueue.main.async {
    NotificationCenter.default.post(name: .dataDownloadComplete, object: self, userInfo: self.dataCounts)
}

extension Notification.Name {
    static let dataDownloadComplete = Notification.Name("dataDownloadComplete")
}
SwiftUI有
onReceive()
修饰符,但我找不到任何方法将上述内容连接到发布通知的“侦听器”


视图
如何接收此
通知

仅供参考,经过几天的阅读和整理,我发现了这两种接收通知的方法。为方便起见,它们包含在同一视图中。(省略了一些不相关的细节。)

在我的例子中,获取(在后台线程上执行)是将信息批量加载到多个实体的核心数据中。获取完成后,未更新视图

// in the background fetch download class
    ...
    var dataCounts: [DataSources.Source : Int] = [:]
    ...

    // as each source of data has been imported
    self.dataCounts[source] = numberArray.count
    ...


// in a view
import Combine

struct FilteredPurchasesView: View {
 
    private var downloadCompletePublisher: AnyPublisher<Notification, Never> {
        NotificationCenter.default
            .publisher(for: .dataDownloadComplete)
            .eraseToAnyPublisher()
    }
    
    private var publisher = NotificationCenter.default
        .publisher(for: .dataDownloadComplete)
        .map { notification in
            return notification.userInfo as! [DataSources.Source : Int]
        }
       .receive(on: RunLoop.main)

    var body: some View {
        List {
            ForEach(numbers.indices, id: \.self) { i in
                NavigationLink(destination: NumberDetailView(number: numbers[i])) {
                    NumberRowView(number: numbers[i])
                }
                .id(i)
            }
        }
        .add(SearchBar(searchText: $numberState.searchText))
        .onReceive(downloadCompletePublisher) { notification in
            print("dataDownload complete (FilteredPurchasesView 1)")
            if let info = notification.userInfo as? [DataSources.Source:Int], let purchaseCount = info[DataSources.Source.purchased] {
                if purchaseCount > 0 {
                    // now the view can be updated/redrawn
                } else {
                    print("purchase update count = 0")
                }
            }
        }
        .onReceive(publisher) { notification in
            print("dataDownload complete (FilteredPurchasesView 2)")
        }
    }
}
//在后台获取下载类中
...
var数据计数:[DataSources.Source:Int]=[:]
...
//因为每个数据源都已导入
self.dataCounts[源]=numberArray.count
...
//看来
进口联合收割机
结构FilteredPurchaseView:视图{
private var downloadCompletePublisher:AnyPublisher{
NotificationCenter.default
.publisher(用于:.dataDownloadComplete)
.删除任何发布者()
}
private var publisher=NotificationCenter.default
.publisher(用于:.dataDownloadComplete)
.map{中的通知
返回notification.userInfo as![DataSources.Source:Int]
}
.receive(打开:RunLoop.main)
var body:一些观点{
名单{
ForEach(numbers.index,id:\.self){i in
导航链接(目的地:NumberDetailView(编号:编号[i])){
NumberRowView(编号:编号[i])
}
.id(i)
}
}
.add(搜索栏(搜索文本:$numberState.searchText))
.onReceive(downloadCompletePublisher){中的通知
打印(“数据下载完成(FilteredPurchaseView 1)”)
如果let info=notification.userInfo as?[DataSources.Source:Int],则let purchaseCount=info[DataSources.Source.purchased]{
如果purchaseCount>0{
//现在可以更新/重画视图
}否则{
打印(“采购更新计数=0”)
}
}
}
.onReceive(发布者){中的通知
打印(“数据下载完成(FilteredPurchaseView 2)”)
}
}
}
关于这一点,请注意:

  • 在前几次尝试中,FilteredPurchaseView尚未初始化。这意味着没有订阅者来监听发布的通知
  • 这两个发布服务器变量都可用。在写这篇文章时,我无法解释它们为什么或如何工作
  • 两个
    onReceive()
    修饰符都包含通知

  • 欢迎评论、想法和反馈。

    这是否回答了您的问题@pawello2222感谢您的链接。那是我看到的一页,让我找到了正确的方向。