问题描述
使用@EnvironmentObject,我创建了一个从ObservableObject继承的类,并且是@Published全局变量的中心.我无法从类内部创建双向绑定.我该怎么做? $在类中不起作用,因为它仅与@State一起使用,而@State在类中不起作用.我需要双向绑定,因为当用户在屏幕上移动一个子实例时,每个子实例都必须具有屏幕位置的实时数据更改.这是我的代码:
Using @EnvironmentObject I created a class that inherits from ObservableObject and is the hub for @Published global variables. I couldn't create a two way binding from within the class though. How can I accomplish that? The $ doesn't work in classes because it only works with @State, and @State doesn't work in classes. I need two-way binding because each child instance must have real-time data change of the screen position when the user moves a child instance around the screen. Here is my code:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var settings: DataBridge
var body: some View {
ZStack {
ForEach(self.settings.childInstances.indices , id: \.self) { index in
self.settings.childInstances[index]
}
VStack {
ForEach(self.settings.childInstanceData.indices, id: \.self) { index in
Text("\(index). y: \(self.settings.childInstanceData[index].height) : x: \(self.settings.childInstanceData[index].width)")
}
}
.offset(y: -250)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
import SwiftUI
struct Child: View {
@EnvironmentObject var settings: DataBridge
@Binding var stateBinding: CGSize
@State var isInitalDrag = true
@State var isOnce = true
@State var currentPosition: CGSize = .zero
@State var newPosition: CGSize = .zero
var body: some View {
Circle()
.frame(width: 50, height: 50)
.foregroundColor(.blue)
.offset(self.currentPosition)
.gesture(
DragGesture()
.onChanged { value in
if self.isInitalDrag && self.isOnce {
// Call function in DataBridge here:
self.settings.addChild()
self.isOnce = false
}
self.currentPosition = CGSize(
width: CGFloat(value.translation.width + self.newPosition.width),
height: CGFloat(value.translation.height + self.newPosition.height)
)
self.stateBinding = self.currentPosition
}
.onEnded { value in
self.newPosition = self.currentPosition
self.isOnce = true
self.isInitalDrag = false
}
)
}
}
struct Child_Previews: PreviewProvider {
static var previews: some View {
Child(stateBinding: .constant(.zero))
}
}
class DataBridge: ObservableObject {
@Published var childInstances: [Child] = []
@Published var childInstanceData: [CGSize] = []
@Published var childIndex = 0
func addChild() {
self.childInstanceData.append(.zero)
// This where I want two-way binding with the childInstanceData array:
self.childInstances.append(Child(stateBinding: $childInstanceData[childIndex]))
self.childIndex += 1
}
}
推荐答案
您所拥有的完全是我会做的,但是我将对Child
What you have is exactly what I would do, but instead I would use custom Binding for the Child
class DataBridge: ObservableObject {
@Published var childInstances: [Child] = []
@Published var childInstanceData: [CGSize] = []
@Published var childIndex = 0
func addChild() {
self.childInstanceData.append(.zero)
// This where I want two-way binding with the childInstanceData array:
let child = Child(stateBinding: Binding(get: {
return self.childInstanceData[self.childIndex]
}, set: {
self.childInstanceData[self.childIndex] = $0
}))
self.childInstances.append(child)
self.childIndex += 1
}
}
这基本上是使用自定义绑定来实现您的目标的.
This basically uses custom binding to achieve your goal.
这篇关于您如何在类中进行双向绑定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!