Home > Net >  SWIFTUI: Problem when switching between items in tabBar. navigationBarTitleDisplayMode
SWIFTUI: Problem when switching between items in tabBar. navigationBarTitleDisplayMode

Time:08-11

the problem is with the navigationBarTitleDisplayMod. It shows whenever it wants and when you switch from one item to another item the name disappears and so does navigationBarTitleDisplayMod. Sitting for a few days I can't figure out the reason.Also, the text in the tabbar does not change when switching.

CONTENTVIEW FILE

import SwiftUI
import Kingfisher

struct ContentView: View {
@EnvironmentObject var viewModel: AuthViewModel

var body: some View {
    Group {
        if viewModel.userSession != nil {
            NavigationView{
                TabView{
                    
                    FeedView()
                        .tabItem{
                            Image(systemName: "house")
                        }
                    
                    SearchView()
                        .tabItem{
                            Image(systemName: "magnifyingglass")
                        }
                    
                    ConversationsView()
                        .tabItem{
                            Image(systemName: "envelope")
                        }
                }
                .navigationTitle("Home")
                .navigationBarItems(leading: Button(action: {
                    viewModel.signOut()
                } , label: {
                    if let user = viewModel.user {
                        KFImage(URL(string: user.profileImageUrl))
                            .resizable()
                            .scaledToFill()
                            .clipped()
                            .frame(width: 32, height: 32)
                            .cornerRadius(16)
                    }
                }))
                .navigationBarTitleDisplayMode(.inline)
            }
        } else {
            LoginView()
        }
    }
}

}

FEEDVIEW FILE

import SwiftUI

struct FeedView: View {
@State var isShowingNewTweetView = false
@ObservedObject var viewModel = FeedViewModel()
var body: some View {
    ZStack(alignment: .bottomTrailing) {
        ScrollView{
            LazyVStack{
                ForEach(viewModel.tweets) { tweet in
                    NavigationLink(destination: TweetsDetailView(tweet: tweet)) {
                        TweetCell(tweet: tweet) 
                    }
                }
            }.padding()
        }
        
        Button(action: { isShowingNewTweetView.toggle() }, label: {
            Image(systemName: "plus")
                .resizable()
                .renderingMode(.template)
                .frame(width: 24, height: 24)
                .padding()
        })
        .background(Color(.systemBlue))
        .foregroundColor(.white)
        .clipShape(Circle())
        .padding()
        .fullScreenCover(isPresented: $isShowingNewTweetView) {
            NewTweetView(isPresented: $isShowingNewTweetView)
        }
    }
}
}

SEARCHVIEW FILE

import SwiftUI

struct SearchView: View {
@State var searchText = ""
@ObservedObject var viewModel = SearchViewModel(config: .search)

var body: some View {
    
    ScrollView{
        SearchBar(text: $searchText)
            .padding(.vertical)
            .padding(.trailing)
        
        VStack(alignment: .leading) {
            ForEach(searchText.isEmpty ? viewModel.users : viewModel.filteredUsers(searchText)) { user in
                HStack { Spacer() }
                NavigationLink(
                    destination: UserProfileView(user: user),
                    label: {
                        UserCell(user: user)
                    })
            }
        }.padding(.leading)
    }
    .autocapitalization(.none)
    .disableAutocorrection(true)
    .navigationBarTitleDisplayMode(.inline)
    .navigationTitle("Search")
}
}

CONVERSATIONVIEW FILE

import SwiftUI

struct ConversationsView: View {
@State var isShowingNewMessageView = false
@State var user : User?
@State var showChat = false
@ObservedObject var viewModel = ConversationViewModel()


var body: some View {
    ZStack(alignment: .bottomTrailing) {
        if let user = user {
            NavigationLink(destination: ChatView(user: user),
                           isActive: $showChat,
                           label: {} )
        }
        ScrollView{
            VStack{
                ForEach(viewModel.recentMessages) {message in
                    NavigationLink(
                        destination: ChatView(user: message.user),
                        label: { ConversationCell(message: message)
                    })
                }
            }.padding()
        }
        
        Button(action: { self.isShowingNewMessageView.toggle()}, label: {
            Image(systemName: "envelope")
                .resizable()
                .scaledToFit()
                .frame(width: 24, height: 24)
                .padding()
        })
        .background(Color(.systemBlue))
        .foregroundColor(.white)
        .clipShape(Circle())
        .padding()
        .sheet(isPresented: $isShowingNewMessageView, content: { NewMessageView(show: $isShowingNewMessageView, startChat: $showChat, user: $user)
        })
    }
}
}

CodePudding user response:

I strongly recommend having multiple NavigationViews within the TabView. There is only ONE NavigationBar for the parent view, and when you switch tabs, you aren't actually navigating anywhere. You will still only have one NavigationView in your NavigationStack, and that's just the TabView. Thus, the NavigationTitles you added to your ChildViews are useless unless there exists a NavigationLink that directs there from some parent OR you make the children views be their own NavigationViews and thus their own navigation stacks.

However, in order to make this work, we can track the selection of the TabView in order to change the NavigationTitle. First let us create an enum.

enum Tabs: Int, CaseIterable {
    case feed
    case search
    case conversation
    
    var title: String {
        switch self {
        case .feed: return "Feed"
        case .search: return "Search"
        case .conversation: return "Conversation"
        }
    }
}

Add to your view

@State private var tabSelection : Tabs = .feed

Add to TabView

TabView(selection: $tabSelection)

And add tags to each view in the TabView like so

.tag(.feed)

And finally for the title in the TabView file

.navigationTitle("\(tabSelection.title)")

Check out this repo explaining TabView and NavigationViews being used together

  • Related