У меня есть меню в приложении, которое смешивает пару UIKit и Swift. Мне нужно получить доступ и обновить состояние меню из разных представлений SwiftUI, которые отличаются от дочерних элементов родительского представления в UIKit. Я могу сделать это, используя EnvironmentObject, но я изо всех сил пытаюсь снова передать одно значение в цикле ForEach.
Вот объект EnvironmentObject, который я создал:
class LateralMenuStatus: ObservableObject {
@Published var status: [FilterButtonStatus] = [.off, .off, .off, .off, .off]
}
Затем я передаю это и перебираю его в цикле ForEach, чтобы снова передать его дочернему компоненту:
Parent: UIKit View --> Child 1: SwiftUI View (I pass the whole status array) --> Children of Child 1: ForEach (pass a single value for each component)
Как правильно передать одно значение и изменить его внутри SwiftUI? Я читал, что в недавней iOS 14 появилось несколько классных обновлений, таких как AppState(), которые могут решить эту проблему, но я хотел бы решить эту проблему в iOS 13.
Большое спасибо,
Не могли бы вы показать свое представление SwiftUI, где используется LateralMenuStatus
?
Если у вас есть объект в среде вашего основного приложения, вы можете использовать переменную @EnvironmentObject для получения ссылки на чтение/запись в любом представлении.
Чтобы передать одно значение из этого объекта во второе дочернее представление, вы можете использовать @Binding. Это чтение/запись, поэтому ваши дочерние представления также могут изменять объект среды, не имея прямой ссылки на родителя.
Я построил приведенный ниже код (обратите внимание, что я использую новое приложение iOS14 для загрузки в объект env, но использование более старого SceneDelegate также будет работать. Уверен, что приведенная ниже логика дочернего представления ForEach ниже — это то, что вы просили...
enum FilterButtonStatus {
case off, on
}
class LateralMenu: ObservableObject {
@Published var status: [FilterButtonStatus] = [.off, .off, .off, .off, .off]
}
@main
struct StackRepApp: App {
@ObservedObject var lateralMenu:LateralMenu = LateralMenu() // declare at App level
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(lateralMenu) // append to first SwiftUI view environment
}
}
}
struct ContentView: View {
@EnvironmentObject var lateralMenu:LateralMenu // retrieve env using @EnvironmentObject
var body: some View {
VStack {
// loop passing each button status to child view
ForEach(0 ..< lateralMenu.status.indices.count) { idx in
ChildView(status: $lateralMenu.status[idx])
}
}
.onAppear(perform: {
// example of changing values on env object
// @envobject is read/write reference
lateralMenu.status[1] = .on
lateralMenu.status[3] = .on
})
}
}
struct ChildView: View {
@Binding var status:FilterButtonStatus // binding lets child view change value
var body: some View {
Button(action:{status = status == .off ? .on : .off}) {
Text("BUTTON")
.foregroundColor(.white)
.padding(20)
.background(status == .on ? Color.green : Color.gray)
}
}
}
Можете ли вы привести минимальный воспроизводимый пример? stackoverflow.com/help/минимально-воспроизводимый-пример