As you can see from the screenshot, the 'Language' tab appears twice.
I've got the following code for HostingTabBar which is called on app startup:
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()
}
}
LanguageView() is:
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()
}
}
Tapping on a row loads 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
The 'Test' tab bar item gets moved to a list in the 'More' tab, with a disclosure indicator that loads TestView when tapped. There's also an edit button in the navigation bar that looks like this when tapped: