0

使用 @EnvironmentObject 我创建了一个继承自 ObservableObject 的类,它是 @Published 全局变量的中心。不过,我无法从类中创建双向绑定。我怎样才能做到这一点?$ 在类中不起作用,因为它只适用于@State,而@State 在类中不起作用。我需要双向绑定,因为当用户在屏幕上移动子实例时,每个子实例都必须具有屏幕位置的实时数据变化。这是我的代码:

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
    }
}
4

1 回答 1

0

你所拥有的正是我会做的,但我会使用自定义绑定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
    }
}

这基本上使用自定义绑定来实现您的目标。

于 2020-07-20T21:42:51.033 回答