How to have a Navigation link open a different view? - swiftui

I keep trying to have the navigation links in the surveys list in contentView to open detailView when selected. I keep getting errors Missing argument for parameter 'newsurvey' in call Insert 'newsurvey: <#Survey#>'
Here's the home view
struct ContentView: View {
#State var surveys: [Survey] = []
#State var isPresented = false
#State var selectedTab: Int = 0
#State private var path = [String]()
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy"
return formatter
}()
var body: some View {
ZStack {
VStack{
NavigationView {
VStack {
Text("")
.frame(height: 0)
.navigationBarTitleDisplayMode(.inline)
//reduces navbartitle height
.toolbar {
ToolbarItem(placement: .principal) {
Image("RR_Logo_Primary_Full_Color")
.resizable()
.frame(width: 275.0, height: 55.0)
}
}
List(surveys) { survey in
NavigationLink(destination: DetailView(newsurvey: survey)) //must be within navigationview
{
HStack{
ZStack {
Rectangle()
.frame(width: 400, height: 100.0)
.foregroundColor(.white)
.cornerRadius(4)
HStack (alignment: .top) {
VStack (alignment: .leading) {
Text(survey.customerName)
.offset(x: -60, y: -2)
.font(.custom("Roboto-Light", size: 24))
Text(survey.lineName)
.offset(x: -60, y: -5)
.font(.custom("Roboto-Light", size: 18))
Text("# of conveyors")
.offset(x: -60)
}
VStack {
Text(dateFormatter.string(from: survey.date))
.font(.custom("Roboto-Light", size: 18))
.offset(x: 60)
}
}
}
}
}
}
.listRowInsets(EdgeInsets())
}
}
.environment(\.defaultMinListHeaderHeight, 1)
CustomTabBar(surveys: $surveys, isPresented: $isPresented)
.frame(height: 60, alignment: .bottom)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I tried the following code below but I keep getting not in scope error.
#State var newsurvey: Survey
#State var surveys: [Survey] = []
#State private var conveyorName = ""
#State private var masterTag = ""
#State private var showAddConveyorSheet = false
#State private var conveyors: [Conveyor] = []
var body: some View {
NavigationView {
VStack {
List {
ForEach(conveyors, id: \.name) { conveyor in
NavigationLink(destination: ConveyorTrack(conveyor: conveyor)) {
Text(conveyor.name)
}
}
}
Button(action: {
self.showAddConveyorSheet = true
}) {
Text("Add Conveyor")
}
}
.navigationBarTitle("Conveyors", displayMode: .inline)
.sheet(isPresented: $showAddConveyorSheet) {
VStack {
HStack {
TextField("Conveyor Name", text: $conveyorName)
TextField("Master Tag", text: $masterTag)
.onTapGesture {
// open camera and scan text here
}
}
Button(action: {
self.conveyors.append(Conveyor(id: self.conveyorName, name: self.conveyorName, masterTag: self.masterTag))
self.conveyorName = ""
self.masterTag = ""
self.showAddConveyorSheet = false
}) {
Text("Save")
}
}
}
}
}
}
struct DetailView_Previews: PreviewProvider {
static var previews: some View {
DetailView(newsurvey: survey)
}
}

Related

View not refreshing when Core Data are updated via another function

EDIT: added more context
I have a List in the ContentView which shows a list of Core Data items. In the list I call the function that should show if one of those items has a "check" that day ( imagine a checklist app ).
The statusView works ok when it loads but it does not refresh when , from a button on the ContentView I create an entry that should effect the fetchRequest.
What I am doing wrong?
This is the statusView:
struct statusView: View {
#FetchRequest var fetchRequest: FetchedResults<Check>
let dateFormatter = DateFormatter()
var body: some View {
if(fetchRequest.count > 0 ) {
Image(systemName: "checkmark")
.imageScale(.large)
.font(.title2)
.foregroundColor(Color(.sRGB, red: 91/255, green: 200/255, blue: 175/255))
} else {
Image(systemName: "exclamationmark.circle")
.imageScale(.large)
.font(.title2)
.foregroundColor(Color.yellow)
}
}
init(filter: String) {
let p1 = NSPredicate(format: "habit_id == %#", filter)
let p2 = NSPredicate(format: "date >= %# && date <= %#", Calendar.current.startOfDay(for: Date()) as CVarArg, Calendar.current.startOfDay(for: Date() + 86400) as CVarArg)
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p1, p2])
_fetchRequest = FetchRequest<Check>(sortDescriptors: [], predicate: predicate)
dateFormatter.dateFormat = "dd/MM/YY"
}
}
and this is the ContentView that is calling the statusView
import SwiftUI
import CoreData
struct ContentView: View {
#Environment(\.managedObjectContext) var moc
#FetchRequest(sortDescriptors: []) var habits: FetchedResults<Habit>
#FetchRequest(sortDescriptors: []) var checks: FetchedResults<Check>
#FetchRequest(sortDescriptors: []) var todayChecks: FetchedResults<Check>
#State private var thisID: String = ""
#State private var selection: String? = nil
#State private var title = ""
#State private var forceRefresh = ""
var color_purple: Color = Color(.sRGB, red: 161/255, green: 78/255, blue: 191/255)
func createCheckToday(habit_id: UUID) {
let new_check = Check(context: moc)
new_check.id = UUID()
new_check.date = Date()
new_check.habit_id = habit_id
try? moc.save()
}
func deleteHabit(obj: NSManagedObject) {
moc.delete(obj)
try! moc.save()
}
func _riga(title: String, subtitle: String, id: UUID, obj: NSManagedObject) -> some View {
print(id.uuidString)
var body: some View {
Button {
createCheckToday(habit_id: id)
} label: {
HStack {
//statusView(filter: id.uuidString)
VStack(alignment: .leading) {
Text(title)
.font(.headline)
Text(subtitle)
.font(.subheadline)
}
}
}
}
return body
}
func delete(at offsets: IndexSet) {
// delete the objects here
}
var body: some View {
NavigationView {
VStack {
Text("")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
HStack {
Image(systemName: "note")
.imageScale(.large)
.font(.title2)
.foregroundColor(Color(.sRGB, red: 161/255, green: 78/255, blue: 191/255))
Text("Habit-o")
.font(Font.system(.largeTitle, design: .rounded).weight(.heavy))
.foregroundColor(Color(.sRGB, red: 161/255, green: 78/255, blue: 191/255))
.padding(10)
}
}
}
//---
List(habits) { habit in
HStack {
statusView(filter: habit.id!.uuidString)
_riga(title: habit.title!, subtitle: habit.subtitle!, id: habit.id!, obj: habit)
}
}
.listStyle(.plain)
Spacer()
//---
NavigationLink(destination: newForm(), tag: "A", selection: $selection) { EmptyView() }
Button(action: {
selection="A"
}) {
Text("New Habit")
.font(.title)
.fontWeight(.heavy)
.padding()
.background(color_purple)
.cornerRadius(40)
.foregroundColor(Color.white)
.padding(10)
.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.purple, lineWidth: 5)
)
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
//---->
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

How to convert value of type 'ImagePickerView' to expected argument type 'String' on Swiftui?

I am trying to build an app where a user can insert the name of the movie and can add an image directly into the app from the photo library (using UIKit. Thankfully the part where the user can insert the text and image from the photo library works. My issue is transferring that data from the .sheet to a list. The info in the TextFields that the user inserts works fine and is shown in the list, but the image doesn't show. I keep getting the error "Cannot convert value of type 'ImagePickerView' to expected argument type 'String'". I don't know how to fix this issue. This issue comes in the ContentView.swift file, in the MovieRow struct when I try to insert the Image(). Any help would be appreciated. Thanks in advance.
Below is my ContentView file. d
// ContentView.swift
// MovieListEditttt
//
import SwiftUI
struct ContentView: View {
#State var movieAdd: [MovieAdd] = []
#State private var newMovieName: String = ""
#State private var showNewMovie = false
#State private var newMovieImage = UIImage()
var body: some View {
ZStack {
VStack {
HStack {
Text("Movies Watched Ratings")
.font(.system(size: 40, weight: .black, design: .rounded
))
Spacer()
Button(action: {
self.showNewMovie = true
}) {
Image(systemName: "plus.circle.fill")
.font(.largeTitle)
.foregroundColor(.yellow)
}
}
List{
ForEach(movieAdd) {movie in
movieRow(movieAdd: movie)
}
}
}
if showNewMovie {
BlankView(bGColor: .black)
.opacity(0.5)
.onTapGesture {
self.showNewMovie = false
}
NewMovieView(isShow: $showNewMovie, addMovie: $movieAdd, newMovieName: newMovieName)
.transition(.move(edge: .bottom))
.animation(.interpolatingSpring(stiffness: 200.0, damping: 25.0, initialVelocity: 10.0))
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct movieRow: View {
#ObservedObject var movieAdd : MovieAdd
var body: some View {
VStack {
Image(movieAdd.movieImage)
.resizable()
.frame(width: 100, height: 100)
Text(movieAdd.movieName)
}
}
}
struct BlankView: View {
var bGColor: Color
var body: some View {
VStack {
Spacer()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(bGColor)
.edgesIgnoringSafeArea(.all)
}
}
Here is my MovieAdd.swift file where I initialize all variables that will be put inside the list.
import Foundation
class MovieAdd: ObservableObject, Identifiable {
var id = UUID()
#Published var movieName = ""
#Published var isComplete : Bool = false
#Published var movieImage : ImagePickerView
init(movieName: String, isComplete: Bool = false, movieImage: ImagePickerView) {
self.movieName = movieName
self.isComplete = isComplete
self.movieImage = movieImage
}
}
And here is my NewMovieView.swift file where the user will be able to insert their Movie information into a TextField, and insert an image from their Photos library. Here is also where I used UIKit.
import SwiftUI
struct NewMovieView: View {
#Binding var isShow: Bool
#Binding var addMovie: [MovieAdd]
#State var newMovieName: String = ""
#State var isShowingImagePicker = false
#State var imageInBlackBox = UIImage()
var body: some View {
ScrollView {
VStack {
VStack (alignment: .leading) {
HStack {
Text("Add a New Movie")
.font(.system(.title, design: .rounded))
.bold()
}
ZStack {
VStack {
HStack (alignment: .center){
Spacer()
Image(uiImage: imageInBlackBox)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.border(Color.black, width: 3)
.clipped()
Spacer()
}
VStack {
Spacer()
Button(action: {
self.isShowingImagePicker.toggle()
}, label: {
Text("Select Image")
.font(.system(size: 15))
})
.sheet(isPresented: $isShowingImagePicker, content: { ImagePickerView(isPresented: $isShowingImagePicker, selectedImage: $imageInBlackBox)})
}
}
}
Group {
TextField("Enter the movie name", text: $newMovieName)
.padding()
.background(Color(.systemGray6))
}
Button(action: {
if self.newMovieName.trimmingCharacters(in: .whitespaces) == "" {
return
}
if self.isShowingImagePicker {
return
}
self.isShow = false
self.addMovieTask(movieName: self.newMovieName, movieImage: ImagePickerView(isPresented: $isShowingImagePicker, selectedImage: $imageInBlackBox))
}) {
Text("Save")
.font(.system(.headline, design: .rounded))
.foregroundColor(.red)
}
}
}
.background(Color.white)
}
}
private func addMovieTask(movieName: String, isComplete: Bool = false, movieImage: ImagePickerView) {
let task = MovieAdd(movieName: movieName, movieImage: movieImage)
addMovie.append(task)
}
}
struct NewMovieView_Previews: PreviewProvider {
static var previews: some View {
NewMovieView(isShow: .constant(true), addMovie: .constant([]), newMovieName: "", isShowingImagePicker: true)
}
}
struct ImagePickerView: UIViewControllerRepresentable {
#Binding var isPresented: Bool
#Binding var selectedImage: UIImage
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerView>) -> some UIViewController {
let controller = UIImagePickerController()
controller.delegate = context.coordinator
return controller
}
func makeCoordinator() -> ImagePickerView.Coordinator {
return Coordinator(parent: self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent: ImagePickerView
init(parent: ImagePickerView){
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let selectedImage = info[.originalImage] as? UIImage {
print(selectedImage)
self.parent.selectedImage = selectedImage
}
self.parent.isPresented = false
}
}
func updateUIViewController(_ uiViewController: ImagePickerView.UIViewControllerType, context: UIViewControllerRepresentableContext<ImagePickerView>) {
//
}
}
Change #1:
Your model should usually be a struct unless there's a really compelling reason to make it an ObservableObject. In this case, struct works very well:
struct MovieAdd: Identifiable {
var id = UUID()
var movieName = ""
var isComplete : Bool = false
var movieImage : UIImage
}
Note that I've made movieImage a UIImage.
Change #2:
Use Image(uiImage:) in MovieRow. The MovieAdd property no longer needs #ObservableObject since it's just a struct.
Also notice that types in Swift should be capitalized to follow convention).
struct MovieRow: View {
var movieAdd : MovieAdd
var body: some View {
VStack {
Image(uiImage: movieAdd.movieImage)
.resizable()
.frame(width: 100, height: 100)
Text(movieAdd.movieName)
}
}
}
Complete code in case I forgot to mention any other changes:
struct ContentView: View {
#State var movieAdd: [MovieAdd] = []
#State private var newMovieName: String = ""
#State private var showNewMovie = false
#State private var newMovieImage = UIImage()
var body: some View {
ZStack {
VStack {
HStack {
Text("Movies Watched Ratings")
.font(.system(size: 40, weight: .black, design: .rounded
))
Spacer()
Button(action: {
self.showNewMovie = true
}) {
Image(systemName: "plus.circle.fill")
.font(.largeTitle)
.foregroundColor(.yellow)
}
}
List{
ForEach(movieAdd) {movie in
MovieRow(movieAdd: movie)
}
}
}
if showNewMovie {
BlankView(bGColor: .black)
.opacity(0.5)
.onTapGesture {
self.showNewMovie = false
}
NewMovieView(isShow: $showNewMovie, addMovie: $movieAdd, newMovieName: newMovieName)
.transition(.move(edge: .bottom))
.animation(.interpolatingSpring(stiffness: 200.0, damping: 25.0, initialVelocity: 10.0))
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct MovieRow: View {
var movieAdd : MovieAdd
var body: some View {
VStack {
Image(uiImage: movieAdd.movieImage)
.resizable()
.frame(width: 100, height: 100)
Text(movieAdd.movieName)
}
}
}
struct BlankView: View {
var bGColor: Color
var body: some View {
VStack {
Spacer()
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.background(bGColor)
.edgesIgnoringSafeArea(.all)
}
}
struct MovieAdd: Identifiable {
var id = UUID()
var movieName = ""
var isComplete : Bool = false
var movieImage : UIImage
}
struct NewMovieView: View {
#Binding var isShow: Bool
#Binding var addMovie: [MovieAdd]
#State var newMovieName: String = ""
#State var isShowingImagePicker = false
#State var imageInBlackBox = UIImage()
var body: some View {
ScrollView {
VStack {
VStack (alignment: .leading) {
HStack {
Text("Add a New Movie")
.font(.system(.title, design: .rounded))
.bold()
}
ZStack {
VStack {
HStack (alignment: .center){
Spacer()
Image(uiImage: imageInBlackBox)
.resizable()
.scaledToFill()
.frame(width: 200, height: 200)
.border(Color.black, width: 3)
.clipped()
Spacer()
}
VStack {
Spacer()
Button(action: {
self.isShowingImagePicker.toggle()
}, label: {
Text("Select Image")
.font(.system(size: 15))
})
.sheet(isPresented: $isShowingImagePicker, content: { ImagePickerView(isPresented: $isShowingImagePicker, selectedImage: $imageInBlackBox)})
}
}
}
Group {
TextField("Enter the movie name", text: $newMovieName)
.padding()
.background(Color(.systemGray6))
}
Button(action: {
if self.newMovieName.trimmingCharacters(in: .whitespaces) == "" {
return
}
if self.isShowingImagePicker {
return
}
self.isShow = false
self.addMovieTask(movieName: self.newMovieName, movieImage: ImagePickerView(isPresented: $isShowingImagePicker, selectedImage: $imageInBlackBox))
}) {
Text("Save")
.font(.system(.headline, design: .rounded))
.foregroundColor(.red)
}
}
}
.background(Color.white)
}
}
private func addMovieTask(movieName: String, isComplete: Bool = false, movieImage: ImagePickerView) {
let task = MovieAdd(movieName: movieName, movieImage: movieImage.selectedImage)
addMovie.append(task)
}
}
struct NewMovieView_Previews: PreviewProvider {
static var previews: some View {
NewMovieView(isShow: .constant(true), addMovie: .constant([]), newMovieName: "", isShowingImagePicker: true)
}
}
struct ImagePickerView: UIViewControllerRepresentable {
#Binding var isPresented: Bool
#Binding var selectedImage: UIImage
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePickerView>) -> some UIViewController {
let controller = UIImagePickerController()
controller.delegate = context.coordinator
return controller
}
func makeCoordinator() -> ImagePickerView.Coordinator {
return Coordinator(parent: self)
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let parent: ImagePickerView
init(parent: ImagePickerView){
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let selectedImage = info[.originalImage] as? UIImage {
print(selectedImage)
self.parent.selectedImage = selectedImage
}
self.parent.isPresented = false
}
}
func updateUIViewController(_ uiViewController: ImagePickerView.UIViewControllerType, context: UIViewControllerRepresentableContext<ImagePickerView>) {
//
}
}

List ForEach Problem SwiftUI - ListCells are not visible with List

I realized that when I use nested List - ForEach, I can not see anything inside these codes. But when I remove List I can see all elements inside the view. Unfortunately, without using List I can not use .onDelete and that is a problem.
struct ListsInfoView: View {
#Environment(\.managedObjectContext) private var viewContext
#FetchRequest(entity:CDListModel.entity(),
sortDescriptors: [
NSSortDescriptor(
keyPath:\CDListModel.title,
ascending: true )
]
)var lists: FetchedResults<CDListModel>
#State var isListSelected = false
#State var selectedList : CDListModel!
var body: some View {
List{
ForEach(lists) { list in
Button(action: {
self.selectedList = list
self.isListSelected.toggle()
}) {
ListCell(list: list)
}
}
.onDelete(perform: deleteList)
}
.listStyle(PlainListStyle())
.fullScreenCover(isPresented: $isListSelected) {
ListDetailView(selectedList: $selectedList)
.environment(\.managedObjectContext, viewContext)
}
}
func deleteList(at offsets: IndexSet) {
viewContext.delete(lists[offsets.first!])
PersistenceController.shared.saveContext()
}
}
Like above, I do not see any ListCell but when I remove List { } it is all perfect. Why is that?
My ListCell
struct ListCell: View {
#ObservedObject var list : CDListModel
var body: some View {
HStack{
Image(systemName: "folder")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30, alignment: .center)
.foregroundColor(.yellow)
Text(list.title ?? "")
.foregroundColor(.black)
.font(.system(size: 20, weight: .regular, design: .rounded))
.padding(.leading,10)
Spacer()
Text(String(list.notes?.count ?? 0))
.foregroundColor(.gray)
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
.padding(.horizontal)
}
}
This is my MainView that I call ListsView. Inside of the ListView I am calling ListInfoView if isShowTapped
struct MainView: View {
#Environment(\.managedObjectContext) private var viewContext
#State var searchText = ""
#State var newFolderName = ""
#State var isAddList : Bool = false
#State var isAddNote: Bool = false
var body: some View {
ZStack{
Color(.white)
.edgesIgnoringSafeArea(.all)
NavigationView{
VStack(alignment: .leading){
ScrollView{
SearchBar(text: $searchText)
.environment(\.managedObjectContext, viewContext)
ListsView()
.environment(\.managedObjectContext, viewContext)
ListView
struct ListsView: View {
#Environment(\.managedObjectContext) private var viewContext
#State var isShowTapped: Bool = false
#State var selectedIndex : Int = 0
var body: some View {
VStack {
Spacer()
HStack{
Text("On My iPhone")
.font(.system(size: 20, weight: .semibold, design: .rounded))
Spacer()
Button(action: {
withAnimation{
self.isShowTapped.toggle()
print("slider button tapped")
}
}, label: {
Image(systemName:isShowTapped ? "chevron.down" : "chevron.right")
.foregroundColor(.black)
})
}
.padding(.horizontal)
if isShowTapped {
ListsInfoView()
.environment(\.managedObjectContext, viewContext)
.transition(.scale)
} else {}
Spacer()
}
}
}

SwiftUI TabView not working, it just shows text off screen

I am trying to get a TabView in SwiftUI, but it just doesn't work... My code is here:
import SwiftUI
import SDWebImage
import HalfModal
struct ContentView: View {
#State var launches: [Launch] = []
// #State private var showingAlert = false
#State private var show_modal: Bool = false
#State private var mName: String = ""
#State private var mDate: String = ""
#State private var rID: String = ""
#State private var mImg: String = ""
#State private var mDesc: String = ""
#State private var showingHalfModal: Bool = false
#State private var choices = ["Launches", "Rockets"]
#State private var choice = 0
var rocketNames = ["5e9d0d95eda69955f709d1eb": "Falcon 1", "5e9d0d95eda69973a809d1ec": "Falcon 9", "5e9d0d95eda69974db09d1ed": "Falcon Heavy", "5e9d0d96eda699382d09d1ee": "Starship"]
init() {
UITableView.appearance().separatorStyle = .none
UITableViewCell.appearance().backgroundColor = .clear
UITableView.appearance().backgroundColor = .clear
}
var body: some View {
// Spacer()
// .frame(height: 100)
TabView {
Group {
NavigationView {
ZStack {
VStack {
// Spacer()
// .frame(height: 10)
// Text("SpaceX launch list")
// .font(.largeTitle)
Spacer()
.frame(height: 1)
.navigationBarTitle("Launches")
List {
ForEach(launches, id: \.id) { launch in
// Text("image")
// Image("imagenotfound")
Button(action: {
self.mName = launch.name
self.mDate = Date(timeIntervalSince1970: launch.date_unix).getFormattedDate(format: "dd/MM/yyyy HH:mm:ss")
self.rID = launch.rocket
self.mImg = launch.links.patch.missionPatch ?? "null"
self.mDesc = launch.details ?? "No description"
// sleep(1)
self.show_modal.toggle()
withAnimation {
self.showingHalfModal = true
}
}) {
HStack {
// Image("imagenotfound")
// .resizable()
// .frame(width: 50, height: 50)
URLimageView(urlString: launch.links.patch.missionPatch)
// .frame(width: 50, height: 50)
Group {
Text(launch.name)
.font(.system(size: 23))
.frame(maxWidth: .infinity, alignment: .leading)
.fixedSize(horizontal: false, vertical: true)
Text(Date(timeIntervalSince1970: launch.date_unix).getFormattedDate(format: "dd/MM/yyyy HH:mm:ss"))
.font(.system(size: 11.5))
.foregroundColor(Color.gray)
.frame(maxWidth: .infinity, alignment: .leading)
.fixedSize(horizontal: false, vertical: true)
Spacer()
}
}
}
.buttonStyle(PlainButtonStyle())
// .sheet(isPresented: self.$show_modal) {
// // ModalView(mission: launch.name, date: Date(timeIntervalSince1970: launch.date_unix).getFormattedDate(format: "dd/MM/yyyy HH:mm:ss"), rocket: launch.rocket)
// ModalView(mission: mName, date: mDate, rocket: rID)
// }
}
}.onAppear {
apiCall().getUsers{ (launches) in self.launches = launches}
}.listStyle(SidebarListStyle())
.frame(alignment: .center)
}
if showingHalfModal {
HalfModalView(content: AnyView(VStack(alignment: .leading) {
Text(mDesc)
.padding()
}), header: AnyView(HStack {
URLimageView(urlString: self.mImg)
VStack(alignment: .leading) {
Text(self.mName)
Text(self.mDate)
.font(.system(size: 10))
.foregroundColor(Color.gray)
}}), isPresented: $showingHalfModal)
}
}
}
}
}
.tabItem {
Image(systemName: "flame")
Text("Launches")
}
Text("rockets")
.tabItem {
Image(systemName: "paperplane")
Text("Rockets")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
extension Date {
func getFormattedDate(format: String) -> String {
let dateformat = DateFormatter()
dateformat.dateFormat = format
return dateformat.string(from: self)
}
}
I have tried following numerous tutorials that show that they get successful results, but mine still doesn't work...
Screenshot of issue:
It should show 2 tabs: Launches and Rockets... Any ideas on how to get it working?
Your view is too complex and you misplaced some subviews. If you clear the body a little bit, you can see that you attached tabItem modifiers outside the TabView:
var body: some View {
TabView {
Group {
NavigationView {
// ...
}
}
}
.tabItem {
Image(systemName: "flame")
Text("Launches")
}
Text("rockets")
.tabItem {
Image(systemName: "paperplane")
Text("Rockets")
}
}
Instead, try the following structure:
var body: some View {
TabView {
NavigationView {
// ...
}
.tabItem {
Image(systemName: "flame")
Text("Launches")
}
Text("rockets")
.tabItem {
Image(systemName: "paperplane")
Text("Rockets")
}
}
}
Note: I recommend you extract some views as subviews. Some examples can be found here:
SwiftUI - Can I share functions with an extracted subview?

Using SwiftUI. My Slider/Side-menu launches new Views just fine when clicked but click <back> button and now all the options are 'dead'

Using SwiftUI and a slider/side menu tutorial that I have augmented in order to put actions on each of the side menu selections.
When the side menu is displayed and I tap a menu option, it works great and takes me to a new view with a menu item. But when i tap on and see the side menu still in place, all the menu items are not dead. The menu items still animate a click (with a flicker) but nothing happens. I have to close the side menu, reopen it, and then the menu items work once again - one time.
Can anyone tell me why this is happening?
Here is the pretty contentview, the mainview, and the sidemenu view.
//ContentView.swift
import SwiftUI
struct ContentView: View {
#State var showMenu = false
var body: some View {
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.showMenu = false
}
}
}
return NavigationView {
GeometryReader { geometry in
ZStack(alignment: .leading) {
MainView(showMenu: self.$showMenu)
.frame(width: geometry.size.width, height: geometry.size.height)
.offset(x: self.showMenu ? geometry.size.width/2 : 0)
.disabled(self.showMenu ? true : false)
if self.showMenu {
MenuView()
.frame(width: geometry.size.width/2)
.transition(.move(edge: .leading))
}
}
.gesture(drag)
}
.navigationBarTitle("Side Menu", displayMode: .inline)
.navigationBarItems(leading: (
Button(action: {
withAnimation {
self.showMenu.toggle()
}
}) {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
}
))
}
}
}
struct MainView: View {
#Binding var showMenu: Bool
var body: some View {
Button(action: {
withAnimation {
self.showMenu = true
}
}) {
Text("Show Menu")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
and here is the sidemenu view.
//MenuView.swift
import SwiftUI
struct PlayerView: View {
#State var showMenu = true
//#EnvironmentObject var session: SessionStore
var body: some View {
VStack{
//self.showMenu = true
Text("Manage Players Here").foregroundColor(.red)
}
}
}
struct MenuView: View {
#State var showMenu = true
var body: some View {
VStack(alignment: .leading) {
HStack() {
NavigationLink(destination: PlayerView()) {
HStack(){
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Players")
.foregroundColor(.gray)
.font(.headline)
}
}
}
.padding(.top, 100)
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
.edgesIgnoringSafeArea(.all)
}
}
struct MenuView_Previews: PreviewProvider {
static var previews: some View {
MenuView()
}
}
enter code here
1) Binding var in the MenuView
2) OnAppear{} with Zstack to turn off the showMenu
struct ContentView: View {
#State var showMenu = false
var body: some View {
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.showMenu = false
}
}
}
return NavigationView {
GeometryReader { geometry in
ZStack(alignment: .leading) {
MainView(showMenu: self.$showMenu)
.frame(width: geometry.size.width, height: geometry.size.height)
.offset(x: self.showMenu ? geometry.size.width/2 : 0)
.disabled(self.showMenu ? true : false)
if self.showMenu {
MenuView(showMenu: self.$showMenu)
.frame(width: geometry.size.width/2)
.transition(.move(edge: .leading))
}
}
.gesture(drag).onAppear {
self.showMenu = false
}
}
.navigationBarTitle("Side Menu", displayMode: .inline)
.navigationBarItems(leading: (
Button(action: {
withAnimation {
self.showMenu.toggle()
}
}) {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
}
))
}
}
}
struct MainView: View {
#Binding var showMenu: Bool
var body: some View {
Button(action: {
withAnimation {
self.showMenu = true
}
}) {
Text("Show Menu")
}
}
}
struct PlayerView: View {
#State var showMenu = true
//#EnvironmentObject var session: SessionStore
var body: some View {
VStack{
//self.showMenu = true
Text("Manage Players Here").foregroundColor(.red)
}
}
}
struct MenuView: View {
#Binding var showMenu: Bool // = true
var body: some View {
VStack(alignment: .leading) {
HStack() {
NavigationLink(destination: PlayerView()) {
HStack(){
Image(systemName: "person")
.foregroundColor(.gray)
.imageScale(.large)
Text("Players")
.foregroundColor(.gray)
.font(.headline)
}
}
}
.padding(.top, 100)
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
.edgesIgnoringSafeArea(.all)
}
}