I have spent more time than I would like to admit on this bug and any help would be appreciated.
The bug occurs in this line of code in the fetchUserData() function
guard let userId = supabase.auth.user()?.id as? String else {
Here is the HomeViewModel.swift file
import Foundation
import SwiftUI
import Combine
import Supabase
class HomeViewModel: ObservableObject {
@Published var username: String = ""
private var cancellables = Set<AnyCancellable>()
private let userDataAccess: UserDataAccess
private let supabase = SupabaseClient(supabaseURL: URL(string: Config.supabaseURL)!, supabaseKey: Config.supabaseKey)
init() {
userDataAccess = UserDataAccess(supabase: supabase)
fetchUserData()
}
private func fetchUserData() {
guard let userId = supabase.auth.user()?.id as? String else {
return
}
userDataAccess.retrieveUserData(user_id: userId) { [weak self] result in
DispatchQueue.main.async {
switch result {
case .success(let userData):
self?.username = userData.display_name
case .failure(let error):
print("Failed to fetch user data: \(error)")
}
}
}
}
}
Here is the UserDataAccess file
import Supabase
import Foundation
class UserDataAccess {
private let supabase: SupabaseClient
init(supabase: SupabaseClient) {
self.supabase = supabase
}
func retrieveUserData(user_id: String, completion: @escaping (Result<UserData, Error>) -> Void) {
let query = supabase.database
.from("user_data")
.select(columns: "*")
.filter(column: "user_id", operator: .eq, value: user_id)
.single()
Task {
do {
let response: UserData = try await query.execute().value
completion(.success(response))
} catch {
completion(.failure(error))
}
}
}
func insertUserData(userData: UserData, completion: @escaping (Result<UserData, Error>) -> Void) {
do {
let encoder = JSONEncoder()
let jsonData = try encoder.encode(userData)
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any] {
let encodableObject = jsonObject.mapValues { AnyEncodable($0) }
let query = supabase.database
.from("user_data")
.insert(values: encodableObject, returning: .representation)
.single()
Task {
do {
let response: UserData = try await query.execute().value
completion(.success(response))
} catch {
completion(.failure(error))
}
}
} else {
completion(.failure(NSError(domain: "InsertUserDataError", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to convert userData to JSON"])))
}
} catch {
completion(.failure(error))
}
}
}
Here is the UserData file
import Foundation
struct UserData: Codable {
let user_id: String
let display_name: String
let age: Int
let gender: String
let height: Double?
let weight: Double?
let fitness_goal: String
enum CodingKeys: String, CodingKey {
case user_id = "user_id"
case display_name = "display_name"
case age = "age"
case gender = "gender"
case height = "height"
case weight = "weight"
case fitness_goal = "fitness_goal"
}
}
Thank you very much