使联合直通发布者不那么全球化
Making a combine passthrough publisher less global
Swift5,iOS13
我想使用 passthroughSubject 发布者;但我的直觉告诉我它是一个全局变量,因此是非常糟糕的做法。如何使这个全局变量不那么全局,同时仍然可用。这是一些代码来展示我在说什么。
我知道还有很多其他方法可以做到这一点,但我想创建一些简单的代码来说明这个问题。
import SwiftUI
import Combine
let switcher = PassthroughSubject<Void,Never>()
struct SwiftUIViewF: View {
@State var nextPage = false
var body: some View {
VStack {
Text("Switcher")
.onReceive(switcher) { (_) in
self.nextPage.toggle()
}
if nextPage {
Page1ViewF()
} else {
Page2ViewF()
}
}
}
}
struct Page1ViewF: View {
var body: some View {
Text("Page 1")
.onTapGesture {
switcher.send()
}
}
}
struct Page2ViewF: View {
var body: some View {
Text("Page 2")
.onTapGesture {
switcher.send()
}
}
}
struct SwiftUIViewF_Previews: PreviewProvider {
static var previews: some View {
SwiftUIViewF()
}
}
这是可能的解决方案 - 将其保存在父视图中并注入到子视图中:
struct SwiftUIViewF: View {
let switcher = PassthroughSubject<Void,Never>()
@State var nextPage = false
var body: some View {
VStack {
Text("Switcher")
.onReceive(switcher) { (_) in
self.nextPage.toggle()
}
if nextPage {
Page1ViewF(switcher: switcher)
} else {
Page2ViewF(switcher: switcher)
}
}
}
}
struct Page1ViewF: View {
let switcher: PassthroughSubject<Void,Never>
var body: some View {
Text("Page 1")
.onTapGesture {
self.switcher.send()
}
}
}
struct Page2ViewF: View {
let switcher: PassthroughSubject<Void,Never>
var body: some View {
Text("Page 2")
.onTapGesture {
self.switcher.send()
}
}
}
使用 @EnvironmentObject
的示例。
让 SDK 为您负责观察/传递事物,而不是您自己设置。
特别是当您的用途是简单的切换时。
import SwiftUI
import Combine
final class EnvState: ObservableObject { @Published var nextPage = false }
struct SwiftUIViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
VStack {
Text("Switcher")
if env.nextPage {
Page1ViewF()
} else {
Page2ViewF()
}
}
}
}
struct Page1ViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
Text("Page 1")
.onTapGesture {
env.nextPage.toggle()
}
}
}
struct Page2ViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
Text("Page 2")
.onTapGesture {
env.nextPage.toggle()
}
}
}
struct SwiftUIViewF_Previews: PreviewProvider {
static var previews: some View {
SwiftUIViewF().environmentObject(EnvState())
}
}
Swift5,iOS13
我想使用 passthroughSubject 发布者;但我的直觉告诉我它是一个全局变量,因此是非常糟糕的做法。如何使这个全局变量不那么全局,同时仍然可用。这是一些代码来展示我在说什么。
我知道还有很多其他方法可以做到这一点,但我想创建一些简单的代码来说明这个问题。
import SwiftUI
import Combine
let switcher = PassthroughSubject<Void,Never>()
struct SwiftUIViewF: View {
@State var nextPage = false
var body: some View {
VStack {
Text("Switcher")
.onReceive(switcher) { (_) in
self.nextPage.toggle()
}
if nextPage {
Page1ViewF()
} else {
Page2ViewF()
}
}
}
}
struct Page1ViewF: View {
var body: some View {
Text("Page 1")
.onTapGesture {
switcher.send()
}
}
}
struct Page2ViewF: View {
var body: some View {
Text("Page 2")
.onTapGesture {
switcher.send()
}
}
}
struct SwiftUIViewF_Previews: PreviewProvider {
static var previews: some View {
SwiftUIViewF()
}
}
这是可能的解决方案 - 将其保存在父视图中并注入到子视图中:
struct SwiftUIViewF: View {
let switcher = PassthroughSubject<Void,Never>()
@State var nextPage = false
var body: some View {
VStack {
Text("Switcher")
.onReceive(switcher) { (_) in
self.nextPage.toggle()
}
if nextPage {
Page1ViewF(switcher: switcher)
} else {
Page2ViewF(switcher: switcher)
}
}
}
}
struct Page1ViewF: View {
let switcher: PassthroughSubject<Void,Never>
var body: some View {
Text("Page 1")
.onTapGesture {
self.switcher.send()
}
}
}
struct Page2ViewF: View {
let switcher: PassthroughSubject<Void,Never>
var body: some View {
Text("Page 2")
.onTapGesture {
self.switcher.send()
}
}
}
使用 @EnvironmentObject
的示例。
让 SDK 为您负责观察/传递事物,而不是您自己设置。
特别是当您的用途是简单的切换时。
import SwiftUI
import Combine
final class EnvState: ObservableObject { @Published var nextPage = false }
struct SwiftUIViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
VStack {
Text("Switcher")
if env.nextPage {
Page1ViewF()
} else {
Page2ViewF()
}
}
}
}
struct Page1ViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
Text("Page 1")
.onTapGesture {
env.nextPage.toggle()
}
}
}
struct Page2ViewF: View {
@EnvironmentObject var env: EnvState
var body: some View {
Text("Page 2")
.onTapGesture {
env.nextPage.toggle()
}
}
}
struct SwiftUIViewF_Previews: PreviewProvider {
static var previews: some View {
SwiftUIViewF().environmentObject(EnvState())
}
}