使联合直通发布者不那么全球化

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())
  }
}