Как сделать двустороннюю привязку внутри класса?

Используя @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
    }
}

1 ответ

Решение

У вас есть именно то, что я сделал бы, но вместо этого я бы использовал настраиваемую привязку для 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
    }
}

Это в основном использует настраиваемую привязку для достижения вашей цели.

Другие вопросы по тегам