在SwiftUI中使用TabView时,第一个选项卡栏按钮出现两次

yptwkmov  于 2023-03-11  发布在  Swift
关注(0)|答案(5)|浏览(106)

正如您在屏幕截图中所看到的,“Language”选项卡出现了两次。

我得到了HostingTabBar的以下代码,它在应用程序启动时调用:

struct HostingTabBar: View {
    
    private enum Tab: Hashable {
        case language
        case canvas
        case homework
        case test
        case more
    }
    
    @State private var selectedTab: Tab = .language
    
    var body: some View {
        TabView(selection: $selectedTab) {
        LanguageView()
            .tag(0)
            .tabItem {
                Text("Language")
                Image("language")
            }
        CanvasView()
            .tag(1)
            .tabItem {
                Text("Canvas")
                Image("canvas")
            }
        HomeworkView()
            .tag(2)
            .tabItem {
                Text("Homework")
                Image("homework")
            }
        TestView()
            .tag(3)
            .tabItem {
                Text("Test")
                Image("test")
            }
        MoreView()
            .tag(4)
            .tabItem {
                Text("More")
                Image("more")
            }
        }
        .accentColor(nil)
    }
}

struct HostingTabBar_Previews: PreviewProvider {
    static var previews: some View {
        HostingTabBar()
    }
}

语言视图()为:

import CoreData

struct LanguageView: View {
    
    @State private var addLanguageIsPresented: Bool = false
    @State private var text: String = ""
    @State private var languageDuplicateIsPresented: Bool = false
    @State private var selectAll: Bool = false

    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(entity: Languages.entity(), sortDescriptors: [])

    var languages: FetchedResults<Languages>
    
    var body: some View {
        NavigationView {
            List {
                ForEach(languages) { language in
                    NavigationLink(destination: WordsView(language: language)) {
                        LanguageRowView(language: language, selectAll: selectAll)
                    }
                }
                .onDelete { indexSet in
                    for index in indexSet {
                        viewContext.delete(languages[index])
                    }
                    do {
                        try viewContext.save()
                    } catch {
                        print(error.localizedDescription)
                    }
                }
                .frame(width: screenSize.width - 30, height: 50)
            }
            .navigationBarTitle("Language", displayMode: .inline).opacity(0.8)
            .background(Color.init(.systemGroupedBackground))
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarLeading) {
                    Button(action: {
                        self.text = ""
                        self.addLanguageIsPresented = true
                        print("add Language is presented is: \(self.addLanguageIsPresented)")
                    }, label: {
                        Image("addLanguage")
                            .foregroundColor(.green)
                    })
                    
                    Button(action: {
                        print("selectAll is: \(selectAll) before selection")
                        if selectAll { selectAll = false } else { selectAll = true }
                        print("selectAll is: \(selectAll) after selection")
                    }, label: {
                        if selectAll { Image("unSelectAll") } else { Image("selectAll") }
                    })
                }
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    Button(action: {
                        
                    }, label: {
                        Image("keyboards")
                            .foregroundColor(.green)
                    })
                    
                    Button(action: {
            
                    }, label: {
                        Image("delete")
                            .foregroundColor(.green)
                    })
                }
            }
        }
        
        addLanguageAlert(title: "Add Language or Sub-Division", isShown: $addLanguageIsPresented, text: $text, onDone: { text in
            print("Inside addLanguageAlert")
            guard text.count > 0 else { return }
            
            // submit language to the addAndSaveLanguage method
            let newLanguage = Languages(context: viewContext)
            newLanguage.name = text
            newLanguage.ckupload = true

            let selectedLanguage = languages.filter { $0.selected == true }
            if selectedLanguage.count > 0 {
                newLanguage.selected = false
            } else {
                newLanguage.selected = true
            }
            newLanguage.setAsHomework = false
            newLanguage.selectedHomework = false
            newLanguage.tickedHomework = false
            newLanguage.tickedLanguage = false

            let recordName = "idlanguage-\(UUID())"
            let zone = CKRecordZone(zoneName: "languagesList")
            let identification = CKRecord.ID(recordName: recordName, zoneID: zone.zoneID)
            let record = CKRecord(recordType: "Languages", recordID: identification)
            let coder = NSKeyedArchiver(requiringSecureCoding: true)
            record.encodeSystemFields(with: coder)
            let metadata = coder.encodedData
            newLanguage.ckmetadata = metadata
            newLanguage.ckrecordname = recordName

            do {
                try viewContext.save()
                print("Language saved.")
            } catch {
                print(error.localizedDescription)
            }
        })
    }
}

struct LanguageView_Previews: PreviewProvider {
    static var previews: some View {
        LanguageView()
    }
}

点击行将加载wordsView():

import CoreData

struct WordsView: View {
        
    @State private var addWordIsPresented: Bool = false
    @State private var english: String = ""
    @State private var foreign: String = ""
    @State private var selectAll: Bool = false

    @Environment(\.managedObjectContext) private var viewContext
    
    let language: Languages
    
    var body: some View {
    
        var words = language.words?.allObjects as! [Words]
    
        NavigationView {
            List {
                ForEach(words) { word in
                    WordRowView(word: word, selectAll: selectAll)
                }
                .onDelete { indexSet in
                    for index in indexSet {
                        viewContext.delete(words[index])
                    }
                    do {
                        try viewContext.save()
                    } catch {
                        print(error.localizedDescription)
                    }
                }
                .frame(width: screenSize.width, height: 75)
            }
            .navigationBarTitle("\(language.name ?? "")", displayMode: .inline).opacity(0.8)
            .background(Color.init(.systemGroupedBackground))
        }
        .toolbar {
            ToolbarItemGroup(placement: .navigationBarLeading) {
                Button(action: {
                    self.english = ""
                    self.foreign = ""
                    self.addWordIsPresented = true
                }, label: {
                    Image("addWord")
                })
                    
                Button(action: {
                    print("selectAll is: \(selectAll) before selection")
                    if selectAll { selectAll = false } else { selectAll = true }
                    print("selectAll is: \(selectAll) after selection")
                }, label: {
                    if selectAll { Image("unSelectAll") } else { Image("selectAll") }
                })
            }
            ToolbarItemGroup(placement: .primaryAction) {
                Button(action: {
        
                }, label: {
                    Image("delete")
                })
            }
        }
        
        addWordAlert(title: "Add Word/Phrase", isShown: $addWordIsPresented, english: $english, foreign: $foreign, onDone: { _,_  in
            // pull out the English and foreign words, or an empty string if there was a problem
            english = english.trimmingCharacters(in: .whitespacesAndNewlines)
            foreign = foreign.trimmingCharacters(in: .whitespacesAndNewlines)
            guard english.count > 0 && foreign.count > 0 else { return }
            
            let newWord = Words(context: viewContext)
            newWord.english = english
            newWord.foreign = foreign
            newWord.language = language
            newWord.ckimage = false
            newWord.ckupload = true
            newWord.bonusCorrectAnswers = 0
            newWord.ckreference = self.language.ckrecordname
            newWord.homeworkAttempts = 0
            newWord.homeworkCorrectAnswers = 0
            newWord.image = nil
            newWord.languageAttempts = 0
            newWord.languageCorrectAnswers = 0
            newWord.tickedWord = false
            newWord.tickedSearchWord = false
            newWord.tickedHomework = false
            newWord.tickedSearchHomework = false
            
            words.append(newWord)
                
            let selectedWord = words.filter{ $0.language == language && $0.selected == true }
            if selectedWord.count > 0 {
                newWord.selected = false
            } else {
                newWord.selected = true
            }
                
            let recordName = "idword-\(UUID())"
            let zone = CKRecordZone(zoneName: "languagesList")
            let id = CKRecord.ID(recordName: recordName, zoneID: zone.zoneID)
            let record = CKRecord(recordType: "Words", recordID: id)
            let coder = NSKeyedArchiver(requiringSecureCoding: true)
            record.encodeSystemFields(with: coder)
            let metadata = coder.encodedData
                
            newWord.ckmetadata = metadata
            newWord.ckrecordname = recordName

            do {
                try viewContext.save()
                print("Word saved.")
            } catch {
                print(error.localizedDescription)
            }
        })
    }
}

struct wordsView_Previews: PreviewProvider {
    static var previews: some View {
        HostingTabBar().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}

let screenSize = UIScreen.main.bounds

“测试”选项卡栏项目会被移动到“更多”选项卡的列表中,点击时会有一个显示指示器加载TestView。在导航栏中还有一个编辑按钮,点击时看起来像这样:

k97glaaz

k97glaaz1#

您对.tag(_:)的使用不一致。TabViewselectionTab绑定,而您的标记都是Int(0、1、2等)。若要解决此问题,请将tag(_:)更改为Tab枚举值。
代码:

struct HostingTabBar: View {
    
    private enum Tab: Hashable {
        case language
        case canvas
        case homework
        case test
        case more
    }
    
    @State private var selectedTab: Tab = .language
    
    var body: some View {
        TabView(selection: $selectedTab) {
        LanguageView()
            .tag(Tab.language)
            .tabItem {
                Text("Language")
                Image("language")
            }
        CanvasView()
            .tag(Tab.canvas)
            .tabItem {
                Text("Canvas")
                Image("canvas")
            }
        HomeworkView()
            .tag(Tab.homework)
            .tabItem {
                Text("Homework")
                Image("homework")
            }
        TestView()
            .tag(Tab.test)
            .tabItem {
                Text("Test")
                Image("test")
            }
        MoreView()
            .tag(Tab.more)
            .tabItem {
                Text("More")
                Image("more")
            }
        }
        .accentColor(nil)
    }
}
eivnm1vs

eivnm1vs2#

如果更改顺序,是否会得到两个LanguageView()选项卡?
我遇到了这个问题。我的SwatchListView()包含了一个ScrollView()和一个Spacer()。当我把它们都包含在一个VStack中时,这个问题就消失了。我怀疑在我的例子中,Spacer()可能被分配到了第二个标签页。

llew8vvj

llew8vvj3#

这是因为Spacer()
在复制的页面中,查找不必要的Spacer()并将其删除。通常,出错的Spacer()位于视图的顶部或底部。请记住在删除和检查时进行预览
DJ bon26

cbeh67ev

cbeh67ev4#

好吧,我也遇到过同样的问题,基于this answer,你需要做的事情是将NavigationView(你复制的标签项- LanguageView) Package 在VStack/HStack中,这样就解决了问题。然而,这对我来说没有意义,但确实有效。如果有人知道如何解释为什么会发生这种情况,请去做。

import CoreData

struct LanguageView: View {
    
    @State private var addLanguageIsPresented: Bool = false
    @State private var text: String = ""
    @State private var languageDuplicateIsPresented: Bool = false
    @State private var selectAll: Bool = false

    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(entity: Languages.entity(), sortDescriptors: [])

    var languages: FetchedResults<Languages>
    
    var body: some View {
        VStack {
            NavigationView {
                List {
                    ForEach(languages) { language in
                        NavigationLink(destination: WordsView(language: language)) {
                            LanguageRowView(language: language, selectAll: selectAll)
                        }
                    }
                    .onDelete { indexSet in
                        for index in indexSet {
                            viewContext.delete(languages[index])
                        }
                        do {
                            try viewContext.save()
                        } catch {
                            print(error.localizedDescription)
                        }
                    }
                    .frame(width: screenSize.width - 30, height: 50)
                }
                .navigationBarTitle("Language", displayMode: .inline).opacity(0.8)
                .background(Color.init(.systemGroupedBackground))
                .toolbar {
                    ToolbarItemGroup(placement: .navigationBarLeading) {
                        Button(action: {
                            self.text = ""
                            self.addLanguageIsPresented = true
                            print("add Language is presented is: \(self.addLanguageIsPresented)")
                        }, label: {
                            Image("addLanguage")
                                .foregroundColor(.green)
                        })
                        
                        Button(action: {
                            print("selectAll is: \(selectAll) before selection")
                            if selectAll { selectAll = false } else { selectAll = true }
                            print("selectAll is: \(selectAll) after selection")
                        }, label: {
                            if selectAll { Image("unSelectAll") } else { Image("selectAll") }
                        })
                    }
                    ToolbarItemGroup(placement: .navigationBarTrailing) {
                        Button(action: {
                            
                        }, label: {
                            Image("keyboards")
                                .foregroundColor(.green)
                        })
                        
                        Button(action: {
                            
                        }, label: {
                            Image("delete")
                                .foregroundColor(.green)
                        })
                    }
                }
            }
        }
        
        addLanguageAlert(title: "Add Language or Sub-Division", isShown: $addLanguageIsPresented, text: $text, onDone: { text in
            print("Inside addLanguageAlert")
            guard text.count > 0 else { return }
            
            // submit language to the addAndSaveLanguage method
            let newLanguage = Languages(context: viewContext)
            newLanguage.name = text
            newLanguage.ckupload = true

            let selectedLanguage = languages.filter { $0.selected == true }
            if selectedLanguage.count > 0 {
                newLanguage.selected = false
            } else {
                newLanguage.selected = true
            }
            newLanguage.setAsHomework = false
            newLanguage.selectedHomework = false
            newLanguage.tickedHomework = false
            newLanguage.tickedLanguage = false

            let recordName = "idlanguage-\(UUID())"
            let zone = CKRecordZone(zoneName: "languagesList")
            let identification = CKRecord.ID(recordName: recordName, zoneID: zone.zoneID)
            let record = CKRecord(recordType: "Languages", recordID: identification)
            let coder = NSKeyedArchiver(requiringSecureCoding: true)
            record.encodeSystemFields(with: coder)
            let metadata = coder.encodedData
            newLanguage.ckmetadata = metadata
            newLanguage.ckrecordname = recordName

            do {
                try viewContext.save()
                print("Language saved.")
            } catch {
                print(error.localizedDescription)
            }
        })
    }
}

struct LanguageView_Previews: PreviewProvider {
    static var previews: some View {
        LanguageView()
    }
}
yxyvkwin

yxyvkwin5#

在将视图分组为一个视图的任何视图中 Package 视图。

ZStack{ //HStack, ScrollView, NavigationStack,etc.
     LanguageView()
}

addLanguageAlert在那里没有主页。你必须把它放在某个地方。

相关问题