您需要PassThroughSubject
在ObservableObject
课堂上提供自定义。看看这段代码:
//
// Created by Франчук Андрей on 08.05.2020.
// Copyright © 2020 Франчук Андрей. All rights reserved.
//
import SwiftUI
import Combine
struct TextChanger{
var textChanged = PassthroughSubject<String,Never>()
public func changeText(newValue: String){
textChanged.send(newValue)
}
}
class ComplexState: ObservableObject{
var objectWillChange = ObservableObjectPublisher()
let textChangeListener = TextChanger()
var text: String = ""
{
willSet{
objectWillChange.send()
self.textChangeListener.changeText(newValue: newValue)
}
}
}
struct CustomState: View {
@State private var text: String = ""
let textChangeListener: TextChanger
init(textChangeListener: TextChanger){
self.textChangeListener = textChangeListener
print("did init")
}
var body: some View {
Text(text)
.onReceive(textChangeListener.textChanged){newValue in
self.text = newValue
}
}
}
struct CustomStateContainer: View {
//@ObservedObject var state = ComplexState()
var state = ComplexState()
var body: some View {
VStack{
HStack{
Text("custom state View: ")
CustomState(textChangeListener: state.textChangeListener)
}
HStack{
Text("ordinary Text View: ")
Text(state.text)
}
HStack{
Text("text input: ")
TextInput().environmentObject(state)
}
}
}
}
struct TextInput: View {
@EnvironmentObject var state: ComplexState
var body: some View {
TextField("input", text: $state.text)
}
}
struct CustomState_Previews: PreviewProvider {
static var previews: some View {
return CustomStateContainer()
}
}
首先,我使用在View中传递to的TextChanger
新值。请注意,在这种情况下得到,而不是. 在最后一种情况下,您将只有in ,而不是 NewValue。在这种情况下将具有旧值。.text
.onReceive(...)
CustomState
onReceive
PassthroughSubject
ObservableObjectPublisher
Publisher.Output
perform: closure
state.text
第二,看ComplexState
课。我创建了一个objectWillChange
属性来使文本更改手动向订阅者发送通知。它几乎和@Published
wrapper 一样。但是,当文本更改时,它会同时发送 和objectWillChange.send()
和textChanged.send(newValue)
。这使您能够准确地选择View
如何对状态变化做出反应。如果您想要普通的行为,只需将状态放入View 中的@ObservedObject
包装器中。CustomStateContainer
然后,您将重新创建所有视图,并且此部分也将获得更新的值:
HStack{
Text("ordinary Text View: ")
Text(state.text)
}
如果您不想重新创建所有这些,只需删除 @ObservedObject。普通文本 View 会停止更新,但 CustomState 会。没有重建。
更新:如果您想要更多控制权,您可以在更改值时决定您希望通知谁有关该更改。检查更复杂的代码:
//
//
// Created by Франчук Андрей on 08.05.2020.
// Copyright © 2020 Франчук Андрей. All rights reserved.
//
import SwiftUI
import Combine
struct TextChanger{
// var objectWillChange: ObservableObjectPublisher
// @Published
var textChanged = PassthroughSubject<String,Never>()
public func changeText(newValue: String){
textChanged.send(newValue)
}
}
class ComplexState: ObservableObject{
var onlyPassthroughSend = false
var objectWillChange = ObservableObjectPublisher()
let textChangeListener = TextChanger()
var text: String = ""
{
willSet{
if !onlyPassthroughSend{
objectWillChange.send()
}
self.textChangeListener.changeText(newValue: newValue)
}
}
}
struct CustomState: View {
@State private var text: String = ""
let textChangeListener: TextChanger
init(textChangeListener: TextChanger){
self.textChangeListener = textChangeListener
print("did init")
}
var body: some View {
Text(text)
.onReceive(textChangeListener.textChanged){newValue in
self.text = newValue
}
}
}
struct CustomStateContainer: View {
//var state = ComplexState()
@ObservedObject var state = ComplexState()
var body: some View {
VStack{
HStack{
Text("custom state View: ")
CustomState(textChangeListener: state.textChangeListener)
}
HStack{
Text("ordinary Text View: ")
Text(state.text)
}
HStack{
Text("text input with full state update: ")
TextInput().environmentObject(state)
}
HStack{
Text("text input with no full state update: ")
TextInputNoUpdate().environmentObject(state)
}
}
}
}
struct TextInputNoUpdate: View {
@EnvironmentObject var state: ComplexState
var body: some View {
TextField("input", text: Binding( get: {self.state.text},
set: {newValue in
self.state.onlyPassthroughSend.toggle()
self.state.text = newValue
self.state.onlyPassthroughSend.toggle()
}
))
}
}
struct TextInput: View {
@State private var text: String = ""
@EnvironmentObject var state: ComplexState
var body: some View {
TextField("input", text: Binding(
get: {self.text},
set: {newValue in
self.state.text = newValue
// self.text = newValue
}
))
.onAppear(){
self.text = self.state.text
}.onReceive(state.textChangeListener.textChanged){newValue in
self.text = newValue
}
}
}
struct CustomState_Previews: PreviewProvider {
static var previews: some View {
return CustomStateContainer()
}
}
我做了一个手动绑定来停止广播objectWillChange。但是您仍然需要在更改此值以保持同步的所有地方获取新值。这就是为什么我也修改了 TextInput。
那是你需要的吗?