swift - 在 SwiftUI 中使用 TabView 时,第一个选项卡栏按钮出现两次
问题描述
从屏幕截图中可以看出,“语言”选项卡出现了两次。
我有以下代码用于在应用程序启动时调用的 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 的披露指示器。导航栏中还有一个编辑按钮,点击时如下所示:
解决方案
您对.tag(_:)
. ' TabView
sselection
是一个Tab
绑定,而您的标签都是Int
s(0、1、2 等)。要解决此问题,请将您tag(_:)
的 s 更改为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)
}
}
推荐阅读
- javascript - 在android上的html输入字段上使用eventlistener的奇怪行为
- java - 尝试在 Ubuntu 中运行 java 命令并引发超出堆大小的错误。如何在 64 位模式下运行?-d64 不起作用
- python - unindent 不匹配任何外部缩进级别这是太空入侵者的游戏
- javascript - 如何告诉 pm2 在部署时使用特定的节点版本
- python - 我必须使用哪些数据类型在 Cython 中编写此函数?
- arrays - 计算不同地理网格大小的两个数组之间的值的偏离或异常
- sql - SQL 查询 GROUP BY MIN?
- c# - 无法在 XAML 中正确设置 RibbonGallery SelectedValue
- python - 如何在 python 中使用形状、位置和比例参数绘制 GEV 分布曲线
- gatling - 模拟组失败的最佳方法