Every time I switch from mock Data to real data from my Firebase, my app crashes:
As soon as I change this 3 lines of code my app crashes
Main Code
import SwiftUI
struct InboxView: View {
@State private var showNewMessageView = false
// @StateObject var viewModel = InboxViewModel() // uncomment this
@State private var user = User.MOCK_USER // comment out this
// private var user: User? { //uncomment this
// return viewModel.currentUser
// }
var body: some View {
NavigationStack {
ScrollView {
ActiveNowView()
List {
ForEach(0 ... 10, id: \.self) { message in
InboxRowView()
}
}
.listStyle(PlainListStyle())
.frame(height: UIScreen.main.bounds.height - 120)
}
.navigationDestination(for: User.self, destination: { user in
ProfileView(user: user)
})
.fullScreenCover(isPresented: $showNewMessageView, content: {
NewMessageView()
})
.toolbar {
ToolbarItem(placement: .topBarLeading) {
HStack {
NavigationLink(value: user) {
CircularProfileImageView(user: user, size: .xsmall)
}
Text("Chats")
.font(.title)
.fontWeight(.semibold)
}
}
ToolbarItem(placement: .topBarTrailing) {
Button {
showNewMessageView.toggle()
} label: {
Image(systemName: "square.and.pencil.circle.fill")
.resizable()
.frame(width: 32, height: 32)
.foregroundStyle(.black, Color(.systemGray5))
}
}
}
}
}
}
InboxViewModel
import Foundation
import Combine
import Firebase
class InboxViewModel: ObservableObject {
@Published var currentUser: User?
private var cancellabels = Set<AnyCancellable>()
init() {
setupSuscribers()
}
private func setupSuscribers() {
UserService.shared.$currentUser.sink { [weak self] user in
self?.currentUser = user
}.store(in: &cancellabels)
}
}
User
import FirebaseFirestore
import SwiftUI
import Firebase
struct User: Codable, Identifiable, Hashable {
@DocumentID var uid: String?
let fullname: String
let email: String
let profileImageUrl: String?
var id: String {
return uid ?? NSUUID().uuidString
}
}
extension User {
static let MOCK_USER = User(fullname: "Bruce Wayne", email: "[email protected]", profileImageUrl: "batman")
}
Authorisation Service
import Foundation
import Firebase
import FirebaseAuth
import FirebaseFirestore
class AuthService {
@Published var userSession: FirebaseAuth.User?
static let shared = AuthService()
init() {
self.userSession = Auth.auth().currentUser
loadCurrentUserData()
print("User session id is \(userSession?.uid)")
}
@MainActor
// Log in
func login(withEmail email: String, password: String) async throws {
do {
let result = try await Auth.auth().signIn(withEmail: email, password: password)
self.userSession = result.user
loadCurrentUserData()
} catch {
print("DEBUG: Failed to sign in user with error: \(error.localizedDescription)")
}
}
@MainActor
// Sign in
func createUser(withEmail email: String, password: String, fullname: String) async throws {
do {
let result = try await Auth.auth().createUser(withEmail: email, password: password)
self.userSession = result.user
try await self.uploadUserData(email: email, fullname: fullname, id: result.user.uid)
loadCurrentUserData()
} catch {
print("DEBUG: Failed to create user with error: \(error.localizedDescription)")
}
}
// Log out
func signOut() {
do {
try Auth.auth().signOut() // signs out on backend
self.userSession = nil // update routing logic
UserService.shared.currentUser = nil
} catch {
print("DEBUG: Failed to sign out with error: \(error.localizedDescription)")
}
}
// Data upload
private func uploadUserData(email: String, fullname: String, id: String) async throws {
let user = User(fullname: fullname, email: email, profileImageUrl: nil)
guard let encodeUser = try? Firestore.Encoder().encode(user) else { return }
try await Firestore.firestore().collection("users").document(id).setData(encodeUser)
}
// bug fix (user details)
private func loadCurrentUserData() {
Task { try await UserService.shared.fetchCurrentUser() }
}
}
The Terminal throws this error as soon as I run my code
I0000 00:00:1732088994.725995 1362774 subchannel:806] subchannel 0x101c70a80 {address=ipv6:%5B2404:6800:4002:81a::200a%5D:443, args={grpc.client_channel_factory=0x60000002b3e0, grpc.default_authority=firestore.googleapis, grpc.http2_scheme=https, grpc.internal.channel_credentials=0x60000263cb40, grpc.internal.client_channel_call_destination=0x103d64828, grpc.internal.event_engine=0x60000002b4e0, grpc.internal.security_connector=0x600002c2d900, grpc.internal.subchannel_pool=0x600002949500, grpc.keepalive_time_ms=30000, grpc.primary_user_agent=grpc-c++/1.65.1, grpc.resource_quota=0x600000c99680, grpc.server_uri=dns:///firestore.googleapis}}: connect failed (UNKNOWN:(domain:NSPOSIXErrorDomain, code:50, description:The operation couldn’t be completed. Network is down) {file:"/var/folders/hn/5bx1f4_d4ds5vhwhkxc7vdcr0000gn/T/ZipRelease/2024-07-25T04-01-28/project-ios/Pods/gRPC-Core/src/core/lib/transport/error_utils", file_line:150, created_time:"2024-11-20T13:19:54.724606+05:30", grpc_status:2}), backing off for 874 ms
DEBUG: Current user is Optional(Messenger.User(_uid: FirebaseFirestore.DocumentID<Swift.String>(value: Optional("Tg2TbvUlWBdjtL1XKkFJD6MeGKn1")), fullname: "Bruce Wayne", email: "[email protected]", profileImageUrl: nil))
Every time I switch from mock Data to real data from my Firebase, my app crashes:
As soon as I change this 3 lines of code my app crashes
Main Code
import SwiftUI
struct InboxView: View {
@State private var showNewMessageView = false
// @StateObject var viewModel = InboxViewModel() // uncomment this
@State private var user = User.MOCK_USER // comment out this
// private var user: User? { //uncomment this
// return viewModel.currentUser
// }
var body: some View {
NavigationStack {
ScrollView {
ActiveNowView()
List {
ForEach(0 ... 10, id: \.self) { message in
InboxRowView()
}
}
.listStyle(PlainListStyle())
.frame(height: UIScreen.main.bounds.height - 120)
}
.navigationDestination(for: User.self, destination: { user in
ProfileView(user: user)
})
.fullScreenCover(isPresented: $showNewMessageView, content: {
NewMessageView()
})
.toolbar {
ToolbarItem(placement: .topBarLeading) {
HStack {
NavigationLink(value: user) {
CircularProfileImageView(user: user, size: .xsmall)
}
Text("Chats")
.font(.title)
.fontWeight(.semibold)
}
}
ToolbarItem(placement: .topBarTrailing) {
Button {
showNewMessageView.toggle()
} label: {
Image(systemName: "square.and.pencil.circle.fill")
.resizable()
.frame(width: 32, height: 32)
.foregroundStyle(.black, Color(.systemGray5))
}
}
}
}
}
}
InboxViewModel
import Foundation
import Combine
import Firebase
class InboxViewModel: ObservableObject {
@Published var currentUser: User?
private var cancellabels = Set<AnyCancellable>()
init() {
setupSuscribers()
}
private func setupSuscribers() {
UserService.shared.$currentUser.sink { [weak self] user in
self?.currentUser = user
}.store(in: &cancellabels)
}
}
User
import FirebaseFirestore
import SwiftUI
import Firebase
struct User: Codable, Identifiable, Hashable {
@DocumentID var uid: String?
let fullname: String
let email: String
let profileImageUrl: String?
var id: String {
return uid ?? NSUUID().uuidString
}
}
extension User {
static let MOCK_USER = User(fullname: "Bruce Wayne", email: "[email protected]", profileImageUrl: "batman")
}
Authorisation Service
import Foundation
import Firebase
import FirebaseAuth
import FirebaseFirestore
class AuthService {
@Published var userSession: FirebaseAuth.User?
static let shared = AuthService()
init() {
self.userSession = Auth.auth().currentUser
loadCurrentUserData()
print("User session id is \(userSession?.uid)")
}
@MainActor
// Log in
func login(withEmail email: String, password: String) async throws {
do {
let result = try await Auth.auth().signIn(withEmail: email, password: password)
self.userSession = result.user
loadCurrentUserData()
} catch {
print("DEBUG: Failed to sign in user with error: \(error.localizedDescription)")
}
}
@MainActor
// Sign in
func createUser(withEmail email: String, password: String, fullname: String) async throws {
do {
let result = try await Auth.auth().createUser(withEmail: email, password: password)
self.userSession = result.user
try await self.uploadUserData(email: email, fullname: fullname, id: result.user.uid)
loadCurrentUserData()
} catch {
print("DEBUG: Failed to create user with error: \(error.localizedDescription)")
}
}
// Log out
func signOut() {
do {
try Auth.auth().signOut() // signs out on backend
self.userSession = nil // update routing logic
UserService.shared.currentUser = nil
} catch {
print("DEBUG: Failed to sign out with error: \(error.localizedDescription)")
}
}
// Data upload
private func uploadUserData(email: String, fullname: String, id: String) async throws {
let user = User(fullname: fullname, email: email, profileImageUrl: nil)
guard let encodeUser = try? Firestore.Encoder().encode(user) else { return }
try await Firestore.firestore().collection("users").document(id).setData(encodeUser)
}
// bug fix (user details)
private func loadCurrentUserData() {
Task { try await UserService.shared.fetchCurrentUser() }
}
}
The Terminal throws this error as soon as I run my code
Share Improve this question edited Nov 22, 2024 at 13:22 Anubhav Tomar asked Nov 20, 2024 at 7:52 Anubhav TomarAnubhav Tomar 13 bronze badges 2I0000 00:00:1732088994.725995 1362774 subchannel:806] subchannel 0x101c70a80 {address=ipv6:%5B2404:6800:4002:81a::200a%5D:443, args={grpc.client_channel_factory=0x60000002b3e0, grpc.default_authority=firestore.googleapis, grpc.http2_scheme=https, grpc.internal.channel_credentials=0x60000263cb40, grpc.internal.client_channel_call_destination=0x103d64828, grpc.internal.event_engine=0x60000002b4e0, grpc.internal.security_connector=0x600002c2d900, grpc.internal.subchannel_pool=0x600002949500, grpc.keepalive_time_ms=30000, grpc.primary_user_agent=grpc-c++/1.65.1, grpc.resource_quota=0x600000c99680, grpc.server_uri=dns:///firestore.googleapis}}: connect failed (UNKNOWN:(domain:NSPOSIXErrorDomain, code:50, description:The operation couldn’t be completed. Network is down) {file:"/var/folders/hn/5bx1f4_d4ds5vhwhkxc7vdcr0000gn/T/ZipRelease/2024-07-25T04-01-28/project-ios/Pods/gRPC-Core/src/core/lib/transport/error_utils", file_line:150, created_time:"2024-11-20T13:19:54.724606+05:30", grpc_status:2}), backing off for 874 ms
DEBUG: Current user is Optional(Messenger.User(_uid: FirebaseFirestore.DocumentID<Swift.String>(value: Optional("Tg2TbvUlWBdjtL1XKkFJD6MeGKn1")), fullname: "Bruce Wayne", email: "[email protected]", profileImageUrl: nil))
- 1 "Network is down", have you enabled network access for your app? (Signing & Capabilities -> App Sandbox -> Incoming/Outgoing connections) – Joakim Danielson Commented Nov 20, 2024 at 8:08
- It's already enabled. – Anubhav Tomar Commented Nov 20, 2024 at 9:04
1 Answer
Reset to default 0The app crashes when switching from mock data to real Firebase data. The terminal log includes a Network is down error and shows that the profileImageUrl is nil, leading to a crash when rendering the profile image.
Update the User Code :
var safeProfileImageUrl: String {
return profileImageUrl ?? "defaultImageURL"
}
When switching from mock data to real data, the InboxViewModel is responsible for fetching and observing the real user data. If the currentUser is nil, your app may crash when trying to access properties like profileImageUrl.