swift - 使用组合获取枚举发布者
问题描述
如何在 Combine 中获取枚举值的 Publisher?
我想在枚举属性更新以使用组合处理值并为详细说明的值创建新的发布者时收到通知。
我使用硬编码字符串为标签 &co 创建了一个我想要的工作示例。你可以在这里找到https://gist.github.com/alessionossa/543a18a55423d98fc415be9edebbddb5。在这个示例中,我可以简单地使用highlightedPanel
没有任何组合代码,但在我的实际项目中,有一个更复杂的逻辑需要使用组合。现在我想使用枚举来识别 NavigationLinks 来完成此操作。
这是代码示例:
import SwiftUI
import Combine
struct ContentView: View {
enum SectionPane: Equatable, Identifiable, CustomStringConvertible {
case servers
case snippets
var description: String {
switch self {
case .servers:
return "server"
case .snippets:
return "snippet"
}
}
var id: SectionPane { self }
}
@State var selectedPane: SectionPane? = nil
// BUG workaround, suggested at https://stackoverflow.com/questions/61003652/selection-in-navigationlink-is-not-working
@State var highlightedPane: SectionPane? = nil
// Subscribe to highlightedPane update to update active var
private var isActivePublisher: AnyPublisher<String, Never> {
// SPOILER: Value of type 'ContentView.SectionPane' has no member 'publisher'
return highlightedPane?.publisher
.map { $0.description }
.eraseToAnyPublisher() ??
Just("").eraseToAnyPublisher()
}
@State private var active: String = ""
var body: some View {
NavigationView {
VStack(alignment: .leading) {
// Current selection label
Text("Selected: \(active)")
NavigationLink(destination: Text("first view").onAppear{ self.highlightedPane = SectionPane.servers }, tag: SectionPane.servers, selection: $selectedPane) {
Text("First")
}
NavigationLink(destination: Text("second view").onAppear{ self.highlightedPane = SectionPane.snippets }, tag: SectionPane.snippets, selection: $selectedPane) {
Text("Second")
}
Spacer()
}.onReceive(isActivePublisher, perform: { selection in
self.active = selection
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
解决方案
如何让世界更简单,如下所示......
enum SectionPane: Equatable, Identifiable, CustomStringConvertible {
case servers
case snippets
var description: String {
switch self {
case .servers:
return "server"
case .snippets:
return "snippet"
}
}
var id: SectionPane { self }
}
class SectionPaneViewModel: ObservableObject {
@Published var highlightedPane: SectionPane? = nil
@Published var selectedPane: SectionPane? = nil
}
struct TestEnumPublisher: View {
@ObservedObject var vm = SectionPaneViewModel()
@State private var active: String = ""
var body: some View {
NavigationView {
VStack(alignment: .leading) {
// Current selection label
Text("Selected: \(active)")
NavigationLink(destination: Text("first view").onAppear{ self.vm.highlightedPane = .servers },
tag: SectionPane.servers, selection: $vm.selectedPane) {
Text("First")
}
NavigationLink(destination: Text("second view").onAppear{ self.vm.highlightedPane = .snippets },
tag: SectionPane.snippets, selection: $vm.selectedPane) {
Text("Second")
}
Spacer()
}.onReceive(vm.$selectedPane, perform: { selection in
self.active = selection?.description ?? "none"
})
}
}
}
推荐阅读
- ruby-on-rails - Rails 5.2 自动加载在开发中不起作用
- java - Intellij 2019.2:GlassFish 需要 Java SE 版本 6。您的 JDK 版本为 0
- python - 带有面向对象代码的 Python line_profiler
- java - 在 Selenium 测试中处理机器人类步骤的替代方法
- printf - printf 在 zsh 中添加神秘的尾随 % 字符
- google-apps-script - 如何从谷歌表格列表自动发送电子邮件
- ios - 在 uianimate 块中有条件语句可以吗?
- amazon-web-services - 每次对 AWS ELB 的第一次请求都很慢
- javascript - 如何遍历数组以获取每个字符串的第一个字符
- xamarin - Xamarin.Forms iOS IdentityServer4 登录重定向问题