使用 TabView 时,“AddItemView”显示为多个按钮,但应该只是一个按钮。每个按钮将用户带到视图的不同部分。例如,一个按钮显示标题,另一个按钮显示列表等。
TabView 代码:
struct MainTabView: View {
var body: some View {
TabView {
ContentView()
.tabItem {
Label("Recipes", systemImage: "list.dash")
}
AddItemView(imageToUpload: Data.init(), recipeStep: [String].init(), stepNumber: [Int].init())
.tabItem {
Label("Add", systemImage: "plus")
}
SettingsView()
.tabItem {
Label("Settings", systemImage: "gearshape.2")
}
}
}
}
实际显示的内容:
如您所见,“添加”重复了多次。
对可能导致这种情况的原因有任何想法吗?
EDIT -- AddItemView 代码
struct AddItemView: View {
@StateObject var viewModel = ViewModel()
@State var imageToUpload: Data
@StateObject var vm = CoreDataRelationshipViewModel()
@Environment(\.presentationMode) var presentationMode
@State var recipeStep: [String]
@State var stepInfo: String = ""
@State var textFieldCount: Int = 1
@State var stepNumber: [Int]
@State var recipeName: String = ""
@State var errorText = ""
@State var stepErrorColor = Color.white.opacity(0)
@State var nameErrorColor = Color.white.opacity(0)
@State var recipesToBind = [StepsEntity].init()
@State var showImage = true
@StateObject var pubRecArray = PublishedRecipeStepAddItemView()
@State private var showingAlert = false
var body: some View {
ZStack {
HStack {
Spacer()
Button(action: {
showingAlert = true
}) {
Image(systemName: viewModel.buttonImage)
}
.alert(isPresented: $showingAlert) { () -> Alert in
Alert(title: Text("Upload Image"), primaryButton: .default(Text("Choose Photo"), action: {
viewModel.choosePhoto()
}), secondaryButton: .default(Text("Take Photo"), action: {
viewModel.takePhoto()
}))
}
//placing the imageview directly in the image section of the button allows for both the camera icon and the uploaded image to be a button
Button(action: {
showingAlert = true
}) {
imageView(for: viewModel.selectedImage)
.frame(width: viewModel.frameDimensionsPublished, height: viewModel.frameDimensionsPublished, alignment: .trailing)
.cornerRadius(10)
}
.alert(isPresented: $showingAlert) { () -> Alert in
Alert(title: Text("Upload Image"), primaryButton: .default(Text("Choose Image"), action: {
viewModel.choosePhoto()
}), secondaryButton: .default(Text("Take Photo"), action: {
viewModel.takePhoto()
}))
}
.buttonStyle(PlainButtonStyle())
Spacer()
}
.fullScreenCover(isPresented: $viewModel.isPresentingImagePicker, content: {
ImagePicker(sourceType: viewModel.sourceType, completionHandler: viewModel.didSelectImage)
})
}
//this is the error popup//
.errorView(text: $errorText)
VStack {
TextField("Recipe Name", text: $recipeName).padding(.bottom).multilineTextAlignment(.leading).font(.title).padding(.leading).overlay(RoundedRectangle(cornerRadius: 10).stroke(nameErrorColor, lineWidth: 1).textFieldStyle(PlainTextFieldStyle()).frame(width: 300, height: 50, alignment: .leading).padding(.trailing, UIScreen.main.bounds.size.width / 5).padding(.bottom))
List {
//using zip, as safer than enumerated
ForEach(Array(zip(pubRecArray.recipeArrayPublished.indices, pubRecArray.recipeArrayPublished)), id: \.0) { index, element in
HStack {
//Text(String(stepNumber[index]) + ".").bold()
//EditorView(container: self.$recipeStep, index: index, text: recipeStep[index])
TextField("", text: Binding<String>(get: { element }, set: { pubRecArray.recipeArrayPublished[index] = $0 }))
}
}
.onDelete(perform: removeRows)
HStack {
TextField("Step \(textFieldCount)", text: $stepInfo).multilineTextAlignment(.leading).padding(.leading).overlay(
RoundedRectangle(cornerRadius: 10).stroke(stepErrorColor, lineWidth: 1).textFieldStyle(PlainTextFieldStyle()).frame(width:100, height: 30, alignment: .leading).padding(.trailing, UIScreen.main.bounds.size.width / 2))
Spacer()
Button(action: {
manageAddStepFlow()
//vm.getRecipeSteps()
}) {
Image(systemName: "plus")
}
.padding()
}
}
//added listStyle to allow list to expand to fill safe area
.listStyle(PlainListStyle())
}
Spacer()
HStack {
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
.cornerRadius(15)
.frame(width: 75, height: 75)
.foregroundColor(.white)
.background(Color(red: 198/255, green: 40/255, blue: 40/255, opacity: 1.0))
.clipShape(Circle())
.font(.body)
.overlay(RoundedRectangle(cornerRadius: 100)
.stroke(Color(red: 198/255, green: 40/255, blue: 40/255, opacity: 1.0)))
Button("Finish") {
errorCheckOnFinishClicked()
}
.cornerRadius(15)
.frame(width: 75, height: 75)
.foregroundColor(.black)
.background(Color(red: 171/255, green: 245/255, blue: 209/255, opacity: 1.0))
.clipShape(Circle())
.font(.body)
.overlay(RoundedRectangle(cornerRadius: 100)
.stroke(Color(red: 171/255, green: 245/255, blue: 209/255, opacity: 1.0)))
}
.navigationTitle("Add Recipe")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
}
}
}
答案 0 :(得分:1)
编辑:
您应该在“AddItemView”中重构您的代码以使其更加模块化。 在任何情况下, 试试这个,直到你重组代码:
struct AddItemView: View {
// ......
var body: some View {
Group { // <--- here
// ...... the messy code that should be made more modular
}
.navigationTitle("Add Recipe")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
}
}
}
编辑:
您可以使用单独的结构来构建代码。 “......这会导致修复吗”,我不知道,但你会 如果组织得当,当然可以更好地理解您的代码。
另一种简单的方法是对您拥有的每个主要模块执行以下操作:
var body: some View {
ZStack {
theAlertView
}
....
}
var theAlertView: some View {
HStack {
Spacer()
Button(action: {
showingAlert = true
}) {
Image(systemName: viewModel.buttonImage)
}
.....
.fullScreenCover(isPresented: $viewModel.isPresentingImagePicker, content: {
ImagePicker(sourceType: viewModel.sourceType, completionHandler: viewModel.didSelectImage)
})
}