admin管理员组

文章数量:1122832

I'm using Firebase and getting an error which leads to perpetual loading on my loginView.

Here is the error I get in the console when I try to create an account (it save the info to the database successfully);

I0000 00:00:1732198505.199351 570520 subchannel:806] subchannel 0x1603cb400 {address=ipv6:%5B2607:f8b0:4007:801::200a%5D:443, args={grpc.client_channel_factory=0x300855160, grpc.default_authority=firestore.googleapis, grpc.http2_scheme=https, grpc.internal.channel_credentials=0x302e04d80, grpc.internal.client_channel_call_destination=0x106089e28, grpc.internal.event_engine=0x300843450, grpc.internal.security_connector=0x302439380, grpc.internal.subchannel_pool=0x3021080e0, grpc.keepalive_time_ms=30000, grpc.primary_user_agent=grpc-c++/1.65.1, grpc.resource_quota=0x3005580f0, grpc.server_uri=dns:///firestore.googleapis}}: connect failed (UNKNOWN:(domain:NSPOSIXErrorDomain, code:50, description:The operation couldn’t be completed. Network is down) {grpc_status:2, created_time:"2024-11-21T06:15:05.198564-08:00", file_line:150, file:"/var/folders/hn/5bx1f4_d4ds5vhwhkxc7vdcr0000gn/T/ZipRelease/2024-07-25T04-01-28/project-ios/Pods/gRPC-Core/src/core/lib/transport/error_utils"}), backing off for 995 ms Saved Successfully

My swiftUI loginView code;


import SwiftUI
import PhotosUI
import Firebase
import FirebaseCore
import FirebaseAuth
import FirebaseStorage
import FirebaseFirestore
import FirebaseStorageCombineSwift
import FirebaseFirestoreCombineSwift


struct LoginView: View {
    // MARK: User Details
    @State var emailID: String = ""
    @State var password: String = ""
    @State var createAccount: Bool = false
    @State var showError: Bool = false
    @State var errorMessage: String = ""
    @State var isLoading: Bool = false
    // MARK User Defaults
    @AppStorage("user_profile_url") var profileURL: URL?
    @AppStorage("user_name") var userNameStored: String = ""
    @AppStorage("user_UID") var userUID: String = ""
    @AppStorage("log_status") var logStatus: Bool = false
    var body: some View {
        VStack(spacing: 10){
            Text("Let's Sign In")
                .font(.largeTitle.bold())
                .hAlign(.leading)
            
            Text("Welcome back, \nYou have been missed")
                .font(.title3)
                .hAlign(.leading)
            
            VStack(spacing: 12){
                TextField("Email", text: $emailID)
                    .textContentType(.emailAddress)
                    .border(1, .gray.opacity(0.5))
                    .padding(.top,25)
                
                SecureField("Password", text: $password)
                    .textContentType(.emailAddress)
                    .border(1, .gray.opacity(0.5))
                    
                Button("Reset password", action: loginUser)
                    .font(.callout)
                    .fontWeight(.medium)
                    .tint(.black)
                    .hAlign(.trailing)
                
                Button(action: loginUser) {
                    
                    // MARK: Login Button
                    Text("Sign In")
                        .font(.title3.bold())
                        .foregroundColor(.white)
                        .hAlign(.center)
                        .fillView(Color("LimeGreen"))
                }
                .padding(.top,10)
                
                Button {
                    createAccount.toggle()
                } label: {
                    // MARK: Login Button
                    Text("Create Account")
                        .font(.title3.bold())
                        .foregroundColor(Color("SignUpTxt"))
                        .hAlign(.center)
                        .fillView(Color("SignUpBtn"))
                }
                .padding(.top,10)
            }
            
            // MARK: Register Button
            VStack {
                HStack{
                    Text("Need Help?")
                        .foregroundColor(Color("LoginText"))
                    
                }
                .padding(.bottom,5)
                
                Button("Reset Password", action: resetPassword)
                    .font(.callout)
                    .fontWeight(.medium)
                    .tint(Color("LimeGreen"))
                    .hAlign(.center)
            }
            .vAlign(.bottom)
        }
        .vAlign(.top)
        .padding(15)
        .overlay(content: {
            LoadingView(show: $isLoading)
        })
        // MARK: Register View VIA Sheets
        .fullScreenCover(isPresented: $createAccount) {
            RegisterView()
        }
        // MARK: Displaying Error/Alert
        .alert(errorMessage, isPresented: $showError, actions: {})
    }
    
    func loginUser(){
        isLoading = true
        Task{
            do{
                try await Auth.auth().signIn(withEmail: emailID, password: password)
                print("User Found")
                try await fetchUser()
            }catch{
                await setError(error)
            }
        }
    }
    
        // MARK: is user found then fetch data from firestore
    func fetchUser()async throws{
        guard let userID = Auth.auth().currentUser?.uid else{return}
        let user = try await Firestore.firestore().collection("Users").document(userID).getDocument(as: User.self)
        // MARK: MUST  UPDAT UI ON MAIN THREAD
        await MainActor.run(body: {
            // Setting UserDefaults data and changing apps auth status
            userUID = userID
            userNameStored = user.username
            profileURL = user.userProfileURL
            logStatus = true
        })
        
    }
    func resetPassword(){
        Task{
            do{
                try await Auth.auth().sendPasswordReset(withEmail: emailID)
                print("Link Sent")
            }catch{
                await setError(error)
            }
        }
        
    }
    
    // MARK: Display error via alert
    func setError(_ error: Error)async{
        // MARK UI must be updated on main thread
        await MainActor.run(body: {
            errorMessage = error.localizedDescription
            showError.toggle()
            isLoading = false
        })
    }
}

// MARK: Register View
struct RegisterView: View{
    // MARK: User Details
    @State var emailID: String = ""
    @State var password: String = ""
    @State var userName: String = ""
    @State var userBio: String = ""
    @State var userBioLink: String = ""
    @State var userProfilePicData: Data?
    // MARK: View Properties
    @Environment(\.dismiss) var dismiss
    @State var showImagePicker: Bool = false
    @State var photoItem: PhotosPickerItem?
    @State var showError: Bool = false
    @State var errorMessage: String = ""
    @State var isLoading: Bool = false
    // MARK: UserDefaults
    @AppStorage("log_status") var logStatus: Bool = false
    @AppStorage("user_profile_url") var profileURL: URL?
    @AppStorage("user_name") var userNameStored: String = ""
    @AppStorage("user_UID") var userUID: String = ""
    
    var body: some View{
        VStack(spacing: 10){
            Text("Create your \nAccount")
                .font(.largeTitle.bold())
                .hAlign(.leading)
            
            Text("Hello, Plant Person \nYou'll love it here!")
                .font(.title3)
                .hAlign(.leading)
            
            // MARK: For smaller Size Optimization
            ViewThatFits {
                ScrollView(. vertical, showsIndicators: false) {
                    HelperView()
                }
                HelperView()
                
            }
            
            // MARK: Register Button
            VStack {
                HStack{
                    Text("Already have an account?")
                        .foregroundColor(Color("LoginText"))
                    
                }
                .padding(.bottom,5)
                
                Button("Login"){
                    dismiss()
                }
                    .font(.callout)
                    .fontWeight(.medium)
                    .tint(Color("LimeGreen"))
                    .hAlign(.center)
            }
            .vAlign(.bottom)
        }
        .vAlign(.top)
        .padding(15)
        .overlay(content: {
            LoadingView(show: $isLoading)
        })
        .photosPicker(isPresented: $showImagePicker, selection: $photoItem)
        .onChange(of: photoItem) {
            oldValue, newValue in
        // MARK: Extracting UIImage PhotoITem
            if let newValue{
                Task{
                    do{
                        guard let imageData = try await newValue.loadTransferable(type: Data.self) else {
                            return }
                        
                        // MARK: UI Must be updated on main thread
                        await MainActor.run{
                            userProfilePicData = imageData
                        }
                    }catch{
                        
                    }
                }
            }
        }
        // MARK Displaying Alert
        .alert(errorMessage, isPresented: $showError, actions:{})
    }
    
    @ViewBuilder
    func HelperView()->some View{
        VStack(spacing: 12){
            
            ZStack{
                if let userProfilePicData,let image = UIImage(data: userProfilePicData){
                    Image(uiImage: image)
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                } else{
                    Image("NullProfileImg")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                }
            }
            .frame(width: 85, height: 85)
            .clipShape(Circle())
            .contentShape(Circle())
            .onTapGesture {
                showImagePicker.toggle()
            }
            .padding(.top,25)
            
            TextField("Username", text: $userName)
                .textContentType(.emailAddress)
                .border(1, .gray.opacity(0.5))
            
            TextField("Email", text: $emailID)
                .textContentType(.emailAddress)
                .border(1, .gray.opacity(0.5))
            
            SecureField("Password", text: $password)
                .textContentType(.emailAddress)
                .border(1, .gray.opacity(0.5))
                
            TextField("About Me", text: $userBio,axis: .vertical)
                .frame(minHeight: 100,alignment: .top)
                .textContentType(.emailAddress)
                .border(1, .gray.opacity(0.5))
            
            TextField("Link", text: $userBioLink)
                .textContentType(.emailAddress)
                .border(1, .gray.opacity(0.5))
            
            Button(action: registerUser){
                // MARK: Login Button
                Text("Create Account")
                    .font(.title3.bold())
                    .foregroundColor(.white)
                    .hAlign(.center)
                    .fillView(Color("LimeGreen"))
            }
            .disableWithOpacity(userName == "" || userBio == "" || emailID == "" || password == "" || userProfilePicData == nil)
            .padding(.top,10)
            
           
        }
    }
    func registerUser(){
        isLoading = true
        Task{
            do{
                // Step 1: Create Firebase Account
                try await Auth.auth().createUser(withEmail: emailID, password: password)
                // Step 2: Upload profile pic to firebase storage
                guard let userUID = Auth.auth().currentUser?.uid else {return}
                guard let imageData = userProfilePicData else {return}
                let storageRef = Storage.storage().reference().child("profile_Images").child(userUID)
                let _ = try await storageRef.putDataAsync(imageData)
                // Step 3: Downlaoding photo url
                let downloadURL = try await storageRef.downloadURL()
                // Step 4: Creating user Firestore object
                let user = User(username: userName, userBio: userBio, userBioLink: userBioLink, userUID: userUID, userEmail: emailID, userProfileURL: downloadURL)
                // Step 5: Saving user doc into firestore database
                let _ = try Firestore.firestore().collection("Users").document(userUID).setData(from: user, completion: {
                    error in
                    if error == nil{
                        // MARK: print successfully saved
                        print("Saved Successfully")
                        userNameStored = userName
                        self.userUID = userUID
                        profileURL = downloadURL
                        logStatus = true
                    }
                })
            }catch{
                // MARK: Deleting created account in case of failure
                try await Auth.auth().currentUser?.delete()
                await setError(error)
            }
        }
        
    }
    
    func resetPassword(){
        Task{
            do{
                try await Auth.auth().sendPasswordReset(withEmail: emailID)
                print("user found")
                
            }catch{
                await setError(error)
            }
        }
    }
    
    // MARK: Displaying Error VIA Alert
    func setError(_ error: Error)async{
        // MARK: UI must be update don main thread
        await MainActor.run(body: {
            errorMessage = error.localizedDescription
            showError.toggle()
            isLoading = false
        })
    }
}


#Preview {
    RegisterView()
}

// MARK: View Extension For UI Building
extension View{
    // MARK: Disabling with opacity
    func disableWithOpacity(_ condition: Bool)->some View{
        self
            .disabled(condition)
            .opacity(condition ? 0.6 : 1)
    }
    
    func hAlign(_ alignment: Alignment)->some View{
        self
            .frame(maxWidth: .infinity,alignment: alignment)
    }

    func vAlign(_ alignment: Alignment)->some View{
        self
            .frame(maxHeight: .infinity,alignment: alignment)
    }
    
    // MARK: Custom border view with padding
    func border(_ width: CGFloat,_ color: Color)->some View{
        self
            .padding(.horizontal,15)
            .padding(.vertical,10)
            .background {
                RoundedRectangle(cornerRadius: 20, style: .continuous)
                    .stroke(color, lineWidth: width)
            }
    }
    
    // MARK: Custom fill view with padding
    func fillView(_ color: Color)->some View{
        self
            .padding(.horizontal,15)
            .padding(.vertical,10)
            .background {
                RoundedRectangle(cornerRadius: 25, style: .continuous)
                    .fill(color)
            }
    }
}

Once a user taps the create account button the app should connect to Firebase storage to save the user info and image and then load to the mainView()

本文标签: iosAnyone know how to fix this Firebase amp SwiftUI app quotNetwork is downquot errorStack Overflow