#swiftui
#swiftui
Вопрос:
Я получаю сбой приложения при использовании представлений с разными размещениями элементов панели инструментов. Ниже приведен фрагмент кода, который позволяет воспроизвести сбой.
Поведение
Я использую 3 представления, каждое со своей собственной определенной панелью инструментов. homeView
и profileView
имеют ту же структуру панели инструментов. Каждый из них использует элемент панели инструментов с .bottomBar
размещением. С addView
другой стороны, элемент панели инструментов на панели инструментов помещен в действие `.cancellationAction’.
При нажатии viewState
элемента панели инструментов значение в ViewModel изменяется. Это приводит к изменению текущего отображаемого представления.
Сообщение об ошибке:
[error] precondition failure: invalid attribute id: 70981 AttributeGraph precondition failure: invalid attribute id: 70981.
Цель
iPhone X 14.0 (18A373)
Фрагмент кода:
import SwiftUI
struct SomeView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
NavigationView() {
content
}
}
private var content: AnyView {
switch(viewModel.viewState) {
case .home: return AnyView(homeView());
case .add: return AnyView(addView());
case .profile: return AnyView(profileView());
}
}
func homeView() -> some View {
Text("Home View")
.toolbar {
ToolbarItem(placement: .bottomBar) {
HStack {
Button("Home", action: { viewModel.setViewState(state: .home) })
Button("Add", action: { viewModel.setViewState(state: .add) })
Button("Profile", action: { viewModel.setViewState(state: .profile) })
}
}
}
}
func addView() -> some View {
Text("Add View")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel", action: { viewModel.setViewState(state: .home)})
}
}
}
func profileView() -> some View {
Text("Profile View")
.toolbar {
ToolbarItem(placement: .bottomBar) {
HStack {
Button("Home", action: { viewModel.setViewState(state: .home) })
Button("Add", action: { viewModel.setViewState(state: .add) })
Button("Profile", action: { viewModel.setViewState(state: .profile) })
}
}
}
}
}
// MARK: View Model
extension SomeView {
class ViewModel: ObservableObject {
@Published var viewState: ViewState
enum ViewState {
case home, add, profile
}
init() {
self.viewState = .home
}
func setViewState(state: ViewState) {
self.viewState = state;
}
}
}
// MARK: Preview
struct SomeView_Previews: PreviewProvider {
static var previews: some View {
SomeView()
}
}
Ответ №1:
Да, для меня это похоже на ошибку.
Возможный обходной путь — поместить каждое представление в отдельный NavigationView
:
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
content
}
@ViewBuilder
var content: some View {
switch viewModel.viewState {
case .home: NavigationView { homeView() }
case .add: NavigationView { addView() }
case .profile: NavigationView { profileView() }
}
}
...
}
Кроме того, вы можете добавить нижнюю панель в addView
:
func addView() -> some View {
Text("Add View")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel", action: { viewModel.setViewState(state: .profile) })
}
ToolbarItem(placement: .bottomBar) {
Text("")
}
}
}
или просто отобразите addView
как sheet
.