SwiftUI - TabView 不止一次显示视图

时间:2021-07-19 01:15:39

标签: swift xcode swiftui tabview

使用 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")
            }

    }
}
}

实际显示的内容:

enter image description here

如您所见,“添加”重复了多次。

对可能导致这种情况的原因有任何想法吗?

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()
        }
    }
}

}

1 个答案:

答案 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)
    })
}