I'm having a weird problem that I can't seem to figure out with SwiftUI. I have a TabView in my ContentView, there are 3 tabs (chat list, user list, and profile) the app loads up on the chat list tab. The problem is, when I select the second tab (user list) it goes to that tab for a split second, then goes right back to the chat list. It doesn't make any sense to me. The 2 main tabs make an API call to get information from a server, and everything is working great, except that first click.
The app loads up, I click the user list tab and it shows for a split second, then goes back to the chat list tab. I can then click the user list tab again and it will go to that tab and stay there, but the first click on that tab always sends you back to the chat list tab.
I'll post up some of my code, hopefully someone will be able to see what I'm doing wrong, because I sure can't.
ContentView
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@State var selectedTab = 0
@State var setup: Bool = false
@State var notificationChatID: String = ""
@ObservedObject var userModel: UserModel = UserModel()
@ObservedObject var chatModel: ChatModel = ChatModel()
@ObservedObject var appState: AppState = AppState.shared
var pushNavigationBinding : Binding<Bool> {
.init { () -> Bool in
appState.selectedChatID != nil
}
set: { (newValue) in
if !newValue {
appState.selectedChatID = nil
}
}
}
let settings = UserDefaults.standard
var body: some View {
ZStack {
if setup {
TabView(selection: $selectedTab) {
ChatList(launchedChatID: appState.selectedChatID ?? "", userModel: userModel, chatModel: chatModel)
.tabItem {
Image(systemName: "message.circle.fill")
Text("Active Chats")
}
UserList(userModel: userModel)
.tabItem {
Image(systemName: "person.3.fill")
Text("User List")
}
ProfileView()
.tabItem {
Image(systemName: "person.crop.circle")
Text("Profile")
}
}
} else {
Onboarding(userModel: userModel, isSetup: $setup)
}
}
.onReceive(NotificationCenter.default.publisher(for: Notification.Name.NewMessage), perform: { notification in
if let info = notification.userInfo {
let chatID = info["chatID"] as? String ?? ""
if chatID != "" {
chatModel.selectedChat = chatID
appState.selectedChatID = chatID
self.notificationChatID = chatID
}
}
})
}
Then my UserList
struct UserList: View {
@ObservedObject var userModel: UserModel
@ObservedObject var chatModel: ChatModel = ChatModel()
@State var action: Int? = -1
var body: some View {
NavigationView {
VStack {
List {
ForEach(0..<userModel.arrayOfUsers.count, id: \.self) { index in
ZStack(alignment: .leading) {
NavigationLink(
destination: ChatView(model: chatModel, userModel: userModel, item: $action),
tag: index,
selection: $action
) {
EmptyView().frame(width: .zero, height: .zero, alignment: .center)
}
Button(action: {
print("You selected \(userModel.arrayOfUsers[index].name)")
userModel.selectedUserName = userModel.arrayOfUsers[index].name
userModel.selectedUserID = userModel.arrayOfUsers[index].id
self.action = index
}) {
Text(userModel.arrayOfUsers[index].name)
}
}
}
}
Spacer()
}.navigationBarTitle(Text("Users"), displayMode: .inline)
}.onAppear() {
print("Inside the userlist on appear")
if userModel.arrayOfUsers.count == 0 {
ApiService.getUsers() { (res) in
switch(res) {
case .success(let response):
print("In success")
let users = response!.users!
DispatchQueue.main.async {
for user in users.users {
userModel.arrayOfUsers.append(user)
}
}
break
case .failure(let error):
print("Error getting users")
print(error)
break
}
}
}
}
}
}
My userModel.arrayOfUsers
is @Published
UserModel
class UserModel: ObservableObject {
var name: String = ""
var id: String = ""
var myUserID: String = ""
@Published var arrayOfUsers: [User] = []
var selectedUserID: String = ""
var selectedUserName: String = ""
}
In the console in Xcode I see
Inside the userlist on appear
...(network stuff)
In the success
In the on appear in ChatList
So it's loading the UserList, it shows the network call out to my API, it shows the In the success
from the API call in the UserList, then the very next thing is back to the In the on appear in ChatList
I can't figure out why it's kicking me back to the chat list.