0

My App currently has two pages, first page has a circle plus button which could lead us to a second page. Basically, I have a save button which after clicking it, we could get back to the rood page. I followed this link for going back to root view. I tried the most up voted code, his code works perfectly. I reduced his code to two scene (basically the same scenario as mine), which also works perfectly. But then I don't know why my own code, pasted below, doesn't work. Basically my way of handling going back to root view is the same as the one in the link.

//
//  ContentView.swift
//  refridgerator_app
//
//  Created by Mingtao Sun on 12/22/20.
//

import SwiftUI
import UIKit
#if canImport(UIKit)
extension View {
    func hideKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

#endif
struct ContentView: View {
    @EnvironmentObject private var fridge : Fridge
    private var dbStartWith=0;
    @State var pushed: Bool = false
    @State private var selection = 1;
    @State private var addFood = false;
    
    var body: some View {
        TabView(selection: $selection) {
            NavigationView {
                List(fridge.container!){
                    food in NavigationLink(destination: FoodView()) {
                        Text("HI")
                    }
                }.navigationBarTitle(Text("Fridge Items"), displayMode: .inline)
                .navigationBarItems(trailing:
                                        NavigationLink(destination: AddFoodView(pushed: self.$pushed),isActive: self.$pushed) {
                                            Image(systemName: "plus.circle").resizable().frame(width: 22, height: 22)
                                        }.isDetailLink(false) )
            }
            .tabItem {
                Image(systemName: "house.fill")
                Text("Home")
            }
            .tag(1)
            
            
            Text("random tab")
                .font(.system(size: 30, weight: .bold, design: .rounded))
                .tabItem {
                    Image(systemName: "bookmark.circle.fill")
                    Text("profile")
                }
                .tag(0)
        }.environmentObject(fridge)
        
    }
}
    

struct FoodView: View{
    var body: some View{
        NavigationView{
            Text("food destination view ");
        }
    }
}

struct AddFoodView: View{
    @Binding var pushed : Bool
    @EnvironmentObject private var fridgeView : Fridge
    @State private var name = ""
    @State private var count : Int = 1
    @State private var category : String = "肉类";
    @State var showCategory = false
    @State var showCount = false
    var someNumberProxy: Binding<String> {
            Binding<String>(
                get: { String(format: "%d", Int(self.count)) },
                set: {
                    if let value = NumberFormatter().number(from: $0) {
                        self.count = value.intValue;
                    }
                }
            )
        }

    var body: some View{
        ZStack{
            NavigationView{
                VStack{
                
                    Button (action: {
                        self.pushed = false ;
                        //let tempFood=Food(id: fridgeView.index!,name: name, count: count, category: category);
                        //fridgeView.addFood(food: tempFood);
                    } ){
                        Text("save").foregroundColor(Color.blue).font(.system(size: 18,design: .default)) }
                }.navigationBarTitle("Three")
            }
                    
            
            ZStack{
                    if self.showCount{
                        Rectangle().fill(Color.gray)
                            .opacity(0.5)
                        VStack(){
                            Spacer(minLength: 0);
                            HStack{
                                Spacer()
                                Button(action: {
                                    self.showCount=false;
                                }, label: {
                                    Text("Done")
                                }).frame(alignment: .trailing).offset(x:-15,y:15)
                            }
                            Picker(selection: $count,label: EmptyView()) {
                                ForEach(1..<100){ number in
                                    Text("\(number)").tag("\(number)")
                                }
                            }.labelsHidden()
                        }            .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
                        .background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
                        .overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
                        .offset(x:10,y:-10)
                        Spacer()
                    }
                    if self.showCategory{
                        let categoryArr = ["肉类","蔬菜类","饮料类","调味品类"]
                        ZStack{
                            Rectangle().fill(Color.gray)
                                .opacity(0.5)
                            VStack(){
                                Spacer(minLength: 0);
                                HStack{
                                    Spacer()
                                    Button(action: {
                                        self.showCategory=false;
                                    }, label: {
                                        Text("Done")
                                    }).frame(alignment: .trailing).offset(x:-15,y:15)
                                }
                                Picker(selection: $category,label: EmptyView()) {
                                    ForEach(0..<categoryArr.count){ number in
                                        Text(categoryArr[number]).tag(categoryArr[number])
                                    }
                                }.labelsHidden()
                            }            .frame(minWidth: 300, idealWidth: 300, maxWidth: 300, minHeight: 250, idealHeight: 100, maxHeight: 250, alignment: .top).fixedSize(horizontal: true, vertical: true)
                            .background(RoundedRectangle(cornerRadius: 27).fill(Color.white.opacity(1)))
                            .overlay(RoundedRectangle(cornerRadius: 27).stroke(Color.black, lineWidth: 1))
                            Spacer()
                        }.offset(x:10,y:20)
                    }
            }
        }.animation(.easeInOut)
    }
        
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

If you read my code carefully, there are some variables are missing referencing. That's because I pasted part of the code that relates to my issue.

Food Class

//
//  Food.swift
//  refridgerator_app
//
//  Created by Mingtao Sun on 12/23/20.
//

import Foundation
class Food: Identifiable {
    init(id:Int, name: String, count: Int, category: String){
        self.id=id;
        self.name=name;
        self.count=count;
        self.category=category;
    }
    var id: Int
    var name: String
    var count: Int
    var category: String
}

Fridge class

//
//  Fridge.swift
//  refridgerator_app
//
//  Created by Mingtao Sun on 12/27/20.
//

import Foundation
class Fridge: ObservableObject{
    init(){
        db=DBhelper();
        let result = setIndex(database: db!);
        self.index = result.1;
        self.container=result.0;
    }
    var db:DBhelper?
    var index : Int?
    @Published var container : [Food]?;
    
    func setIndex(database: DBhelper) -> ([Food],Int){
        let foodList : [Food] = database.read();
        var index=0;
        for food in foodList{
            index = max(food.id,index);
        }
        return (foodList,(index+1));
    }
    
    func updateindex(index: inout Int){
        index=index+1;
    }
    
    func testExist(){
        if let data = db {
            print("hi")
        }
        else{
            print("doesnt exist")
        }
    }
    
    func addFood(food:Food){
        self.db!.insert(id: self.index!, name: food.name, count:food.count, category: food.category);
        self.container!.append(food);
    }
    
    
}
Simon
  • 1,754
  • 14
  • 32
TommySun
  • 57
  • 7
  • "But then I don't know why my own code pasted below does work." Do I understand you correctly that you want an explanation on why your code works right? – Simon Dec 28 '20 at 14:40
  • Could you provide `Fridge` code to test? – Asperi Dec 28 '20 at 14:49
  • @Simon Nah. My code doesn't work as expected. It should go back to root. But it didn't. – TommySun Dec 28 '20 at 14:51
  • @Asperi I provided the code i have for Fridge and Food class. Basically, after pressing save, it should go back to root view (content view) but it didn't. – TommySun Dec 28 '20 at 14:54

1 Answers1

1

Because you implemented a new NaviagtionView in AddFoodView. Simply remove this and it should work. Look at the link you provided. There is no NavigationView in the child.

Correct me if Im wrong but the core code parts here that produce this issue are as follows:

Here you start:

struct ContentView: View {
    
    @State var pushed: Bool = false
    // Deleted other vars
    var body: some View {
        TabView(selection: $selection) {
            NavigationView {
                List(fridge.container!){
                    food in NavigationLink(destination: FoodView()) {
                        Text("HI")
                    }
                }.navigationBarTitle(Text("Fridge Items"), displayMode: .inline)
                .navigationBarItems(trailing:
                                        // Here you navigate to the child view
                                        NavigationLink(destination: AddFoodView(pushed: self.$pushed),isActive: self.$pushed) {
                                            Image(systemName: "plus.circle").resizable().frame(width: 22, height: 22)
                                        }.isDetailLink(false) )
            }

Here you land and want to go back to root:

struct AddFoodView: View{
    
    @Binding var pushed : Bool
    // Deleted the other vars for better view
    
    var body: some View{
        ZStack{
            NavigationView{  // <-- remove this
                VStack{
                
                    Button (action: {
                        // here you'd like to go back
                        self.pushed = false;
                    } ){
                        Text("save").foregroundColor(Color.blue).font(.system(size: 18,design: .default)) }
                }.navigationBarTitle("Three")
            }

For the future:

I have the feeling you might have troubles with the navigation in general.

Actually it is really simple:

You implement one NavigationView at the "root" / start of your navigation. From there on you only use NavigationLinks to go further down to child pages. No NavigationView needed anymore.

Simon
  • 1,754
  • 14
  • 32
  • Hmmm Thanks. I'm such a newbie maybe I didn't understand SwiftUI detailed enough. So navigationView is just like a view for the root right? – TommySun Dec 28 '20 at 15:14
  • You will get the hang of it quite fast I'm sure! Here are some good tutorials. Long one: https://www.youtube.com/watch?v=nA6Jo6YnL9g&feature=emb_title / Short one: https://daddycoding.com/2020/02/17/swiftui-navigationview/ – Simon Dec 28 '20 at 15:19
  • I just tried your code without navigationView. It is not working as expected too. Basically I copied and paste your button action code to my `struct AddFoodView` and try to see if a simple button will take me back to the root page. It did not. – TommySun Dec 29 '20 at 08:42
  • 1
    I just tested. The problem is that in my ContentView. If I use `navigationBarTrailing` or `NavigationBarItem(trailing:navigation link )`, then I wasn't able to pop back, if I use simply a button then I am able to pop back. Do. you probably know how to fix the issue? – TommySun Dec 29 '20 at 08:57
  • I found a thread who has the same issue as mine. I'm going to test the provided answer. I think its kind of a bug. [link](https://stackoverflow.com/questions/57649430/navigationlink-isactive-does-not-work-inside-navigationbaritemstrailing-modif) – TommySun Dec 29 '20 at 09:04
  • Actually it is really simple: "You implement one NavigationView at the "root" / start of your navigation. From there on you only use NavigationLinks to go further down to child pages. No NavigationView needed anymore." - Spot on, I've struggled a lot with this until your answer - write a blog post :) – OakNinja Nov 03 '21 at 20:29