xcode 无法获取要上传到Firebase存储的配置文件映像

5rgfhyps  于 2022-12-30  发布在  其他
关注(0)|答案(1)|浏览(118)

我试过很多次跟随不同的视频讲述如何将个人资料照片上传到Firebase,目前,Auth可以工作,并创建一个具有全名、UID和密码的用户,但Firestore数据库中没有存储图像URL,Firestore存储中也没有存储实际图像。
当用户点击“注册”,我希望帐户被创建,以及图像被存储。
Firebase存储规则:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if 
      request.auth != null;
    }
  }
}

创建帐户验证视图

import SwiftUI

struct CreateAccountAuth: View {
    @State private var email = ""
    @State private var password = ""
    @State private var fullname = ""
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var viewModel: AuthViewModel
    @State private var showImagePicker = false
    @State private var selectedImage: UIImage?
    @State private var profileImage: Image?

        var body: some View {

            VStack(alignment: .leading) {
                Text("Let's get started")
                    .font(.title)
                    .fontWeight(.semibold)

                Button {
                    showImagePicker.toggle()
                } label: {
                    if let profileImage = profileImage {
                        profileImage
                            .resizable()
                            .scaledToFill()
                            .frame(width: 100, height: 100)
                            .cornerRadius(10)
                    } else {
                        Image("EmptyProfile")
                            .resizable()
                            .scaledToFill()
                            .frame(width: 100, height: 100)
                    }
                }
                .padding(.bottom, 24)
                .fullScreenCover(
                    isPresented: $showImagePicker,
                    onDismiss: loadImage) {
                        ImagePicker(image: $selectedImage)
                }
                    
                VStack (alignment:.leading) {
                    CustomInputField(imageName: "person", placeholderText: "Name", text: $fullname)
                        .padding(.bottom, 24)
                    CustomInputField(imageName: "mail", placeholderText: "Email", text: $email)
                        .padding(.bottom, 24)
                    CustomInputField(
                        imageName: "lock",
                        placeholderText: "Password",
                        isSecureField: true,
                        text: $password)
                }.padding(.bottom, 16)

                        VStack {
                            Button {
                                viewModel.register(
                                    withEmail: email,
                                    password: password,
                                    fullname: fullname)
                            } label: {
                                Text("Sign Up")
                                    .font(.headline)
                                    .foregroundColor(.white)
                                    .frame(height: 50)
                                    .frame(maxWidth: .infinity)
                                    .background(Color.accentColor)
                                    .clipShape(Capsule())
                                    .padding(.vertical)
                            }
                            
                            Text("or")
                            
                            Button {
                                print("Continue with phone..")
                            } label: {
                                Text("Sign up with phone")
                                    .font(.headline)
                                    .fontWeight(.regular)
                                    .foregroundColor(.black)
                                    .frame(height: 50)
                                    .frame(maxWidth: .infinity)
                                    .background(Color(.systemGray5))
                                    .clipShape(Capsule())
                                    .padding(.vertical)
                            }
                            Spacer()
                            Button {
                                presentationMode.wrappedValue.dismiss()
                            } label: {
                                HStack {
                                    Text("Already have an account?")
                                        .font(.footnote)
                                    
                                    Text("Sign in")
                                        .font(.footnote)
                                        .fontWeight(.semibold)
                                }
                            }
                            .padding(.bottom, 40)
                        }
                .padding(.top, 56)
            }
        .padding(.top, 40)
        .navigationBarHidden(true)
        .padding(.leading)
        .padding(.trailing)
        }
    
    func loadImage() {
        guard let selectedImage = selectedImage else { return }
        profileImage = Image(uiImage: selectedImage)
    }
}

struct CreateAccountAuth_Previews: PreviewProvider {
    static var previews: some View {
        CreateAccountAuth()
    }
}

验证视图模型视图

import SwiftUI
import FirebaseAuth
import FirebaseCore
import FirebaseStorage
import FirebaseFirestore
import FirebaseFirestoreSwift

class AuthViewModel: ObservableObject {
    @Published var userSession: User?
    @Published var didAuthenticateUser = false
    private var tempUserSession: User?

    init() {
        self.userSession = Auth.auth().currentUser
        
        print("DEBUG: User session is \(self.userSession?.uid)")
    }
    
    func login(withEmail email: String, password: String) {
        Auth.auth().signIn(withEmail: email, password: password) { result, error in if let error = error {
            print("DEBUG: Failed to register with error \(error.localizedDescription)")
            return
            }
            guard let user = result?.user else { return }
            self.userSession = user
            print("DEBUG: Did log user in...")
        }
    }
    
    func register(withEmail email: String, password: String, fullname: String) {
        Auth.auth().createUser(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to register with error \(error.localizedDescription)")
                return
            }
            
            guard let user = result?.user else { return }
            self.tempUserSession = user

            
            print("DEBUG: Registered user successfully")
            print("DEBUG: User is \(self.userSession)")
            
            let data = ["email": email,
                        "fullname": fullname,
                        "uid": user.uid]
            
            Firestore.firestore().collection("users")
                .document(user.uid)
                .setData(data) { _ in
                    self.didAuthenticateUser = true
                }
        }
    }
    
    func signOut() {
        //sets user session to nil so we show login view
        userSession = nil
        tempUserSession = nil
        didAuthenticateUser = false

        
        //signs user out on server(backend)
        try? Auth.auth().signOut()
    }
    
    func uploadProfileImage(_ image: UIImage) {
        guard let uid = tempUserSession?.uid else { return }
        
        ImageUploader.uploadImage(image: image) { profileImageUrl in
            Firestore.firestore().collection("users")
                .document(uid)
                .updateData(["profileImageUrl": profileImageUrl]) { _ in
                    self.userSession = self.tempUserSession
                }
        }
    }
}

图像上传器

import Firebase
import UIKit
import FirebaseStorage

struct ImageUploader {
    
    static func uploadImage(image: UIImage, completion: @escaping(String) -> Void) {
        guard let imageData = image.jpegData(compressionQuality: 0.5) else { return }
        
        let filename = NSUUID().uuidString
        let ref = Storage.storage().reference(withPath: "/profile_image/\(filename)")
        
        ref.putData(imageData, metadata: nil) { _, error in
            if let error = error {
                print("DEBUG: Failed to upload image with error: \(error.localizedDescription)")
                return
            }
            
            ref.downloadURL { imageUrl, _ in
                guard let imageUrl = imageUrl?.absoluteString else { return }
                completion(imageUrl)
            }
        }
    }
}
r1wp621o

r1wp621o1#

问题是您没有调用 AuthViewModel 中的 uploadProfileImage 函数。
为了调用它并传递选中的图像,需要在视图模型中保持图像状态,或者在视图中调用函数,在视图中调用函数需要在register函数中完成闭包,以便等待用户创建完成,这样会比较乱,建议将图像移到视图模型中。

class AuthViewModel: ObservableObject {
    // New state for the selected image 
    @Published var selectedImage: UIImage?

    func register(withEmail email: String, password: String, fullname: String) {
        Auth.auth().createUser(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to register with error \(error.localizedDescription)")
                return
            }
        
            guard let user = result?.user else { return }
            self.tempUserSession = user

        
            print("DEBUG: Registered user successfully")
            print("DEBUG: User is \(self.userSession)")
        
            let data = ["email": email,
                        "fullname": fullname,
                        "uid": user.uid]
        
            Firestore.firestore().collection("users")
                .document(user.uid)
                .setData(data) { _ in
                     self.didAuthenticateUser = true
                }

            // Call your upload profile image function here.
            self.uploadProfileImage(selectedImage)
        }
    }
}

您需要更改 ImagePicker

ImagePicker(image: $viewModel.selectedImage)

还有 loadImage 函数。

func loadImage() {
    guard let selectedImage = viewModel.selectedImage else { return }
    profileImage = Image(uiImage: selectedImage)
}

相关问题