从 Firebase 存储获取图像

问题描述 投票:0回答:1

我在从 Firebase 获取图像时遇到问题,我创建了一个函数来将图像保存到存储中,并且运行良好,但同时我想向用户显示该图像,但它无法正常工作,因为当我关闭视图并单击返回时,我看到了图像。问题出在哪里,如何解决?

用户个人资料视图:

import SwiftUI
import PhotosUI

public struct UserProfileView: View {
    @StateObject private var viewModel = UserProfileViewModel()
    
    public init() { }
    
    public var body: some View {
        VStack {
            if let imageUrlString = viewModel.user?.profileImagePath, let url = URL(string: imageUrlString) {
                AsyncImage(url: url) { image in
                    image
                        .resizable()
                        .scaledToFill()
                        .frame(width: 150, height: 150)
                        .clipShape(Circle())
                } placeholder: {
                    ProgressView()
                        .frame(width: 150, height: 150)
                }
                
            } else {
                Image(systemName: "person.fill")
                    .font(.system(size: 90))
                    .frame(width: 150, height: 150)
            }
        }
        .background {
            Circle()
                .stroke(lineWidth: 3)
        }
        PhotosPicker(
            selection: $viewModel.selectedPhoto,
            matching: .images,
            photoLibrary: .shared()
        ) {
            Text("Change photo")
        }
        .onChange(of: viewModel.selectedPhoto) { newValue in
            if let newValue {
                Task {
                    do {
                        try await viewModel.saveProfileImage(item: newValue)
                        viewModel.objectWillChange.send()
                    } catch {
                        print(error.localizedDescription)
                    }
                }
            }
        }
    }
}

用户配置文件视图模型:

@MainActor
public final class UserProfileViewModel: ObservableObject {
    @Inject private var cloudStorageManager: CloudStorageInterface
    @Inject private var userManager: UserManagerInterface
    @Published var selectedPhoto: PhotosPickerItem? = nil
    @Published var imageUrl: URL? = nil
    @Published var user: User? = nil
    
    public init() {
        Task {
            do {
                try await getCurrentUser()
            } catch {
                print(error.localizedDescription)
            }
        }
    }
    
    private func updateUserProfileImagePath(path: String) async throws {
        let data: [String : Any] = [
            User.CodingKeys.profileImagePath.rawValue : path
        ]
        try await userManager.updateUserData(data: data)
    }
    
    func saveProfileImage(item: PhotosPickerItem) async throws {
            let user = try await self.userManager.fetchUser()
            guard let data = try await item.loadTransferable(type: Data.self) else { return }
        guard let image = UIImage(data: data) else { return }
            let path = try await cloudStorageManager.saveImage(image: image, userId: user.id)
            print("SUCCESS!")
            let url = try await cloudStorageManager.getUrlForImage(path: path)
            try await updateUserProfileImagePath(path: url.absoluteString)
    }
    
    func getCurrentUser() async throws {
        self.user = try await userManager.fetchUser()
    }
    
    func getProfileImage() async throws {
        guard let user = user else { return }
        guard let image = user.profileImagePath else { return }
        self.imageUrl = try await cloudStorageManager.getUrlForImage(path: image)
    }
}

云存储管理器:

final class CloudStorageManager: CloudStorageInterface {
    private lazy var storage = Storage.storage().reference()
    
    private var imagesReference: StorageReference {
        storage.child("images")
    }
    
    private func userReference(userId: String) -> StorageReference {
        storage.child("Users").child(userId)
    }
    
    func saveImage(data: Data, userId: String) async throws -> String {
        let meta = StorageMetadata()
        meta.contentType = "image/jpeg"
        
        let path = "\(UUID().uuidString).jpeg"
        let returnedMetaData = try await userReference(userId: userId).child(path).putDataAsync(data, metadata: meta)
        
        guard let returnedPath = returnedMetaData.path else {
            throw URLError(.badServerResponse)
        }
                
        return returnedPath
    }
    
    //SAVE
    func saveImage(image: UIImage, userId: String) async throws -> String {
        guard let data = image.jpegData(compressionQuality: 0.6) else {
            throw URLError(.backgroundSessionWasDisconnected)
        }
        
        return try await saveImage(data: data, userId: userId)
    }
    
    //READ
    func getUrlForImage(path :String) async throws -> URL {
       try await Storage.storage().reference(withPath: path).downloadURL()
    }
}

用户型号:

public struct User: Storable, Hashable {
    public let id: String
    public let providerId: String?
    public let email: String?
    public let displayName: String?
    public let photoURL: String?
    public let topic: String
    public let mqttPassword: String
    public let isFirstLogin: Bool
    public let profileImagePath: String?
    
    public init(
        id: String = UUID().uuidString,
        providerId: String?,
        email: String?,
        displayName: String?,
        photoURL: String?,
        topic: String,
        mqttPassword: String,
        isFirstLogin: Bool = true,
        profileImagePath: String? = nil
    ) {
        self.id = id
        self.providerId = providerId
        self.email = email
        self.displayName = displayName
        self.photoURL = photoURL
        self.topic = topic
        self.mqttPassword = mqttPassword
        self.isFirstLogin = isFirstLogin
        self.profileImagePath = profileImagePath
    }
    
    public init(
        from authDataResult: AuthenticationDataResult,
        isFirstLogin: Bool = true
    ) {
        self.id = authDataResult.uid
        self.providerId = authDataResult.providerId
        self.email = authDataResult.email
        self.displayName = authDataResult.displayName
        self.photoURL = authDataResult.photoURL
        self.topic = ""
        self.mqttPassword = ""
        self.isFirstLogin = isFirstLogin
        self.profileImagePath = nil
    }
    
    public init(from dao: UserDAO) {
        self.id = dao.id
        self.providerId = dao.providerId
        self.email = dao.email
        self.displayName = dao.displayName
        self.photoURL = dao.photoURL
        self.topic = dao.topic
        self.mqttPassword = dao.mqttPassword
        self.isFirstLogin = dao.isFirstLogin
        self.profileImagePath = dao.profileImagePath
    }
    
    public enum CodingKeys: String, CodingKey {
        case id
        case providerId
        case email
        case displayName
        case photoURL
        case topic
        case mqttPassword
        case isFirstLogin
        case profileImagePath
    }
}
swift firebase swiftui firebase-storage
1个回答
0
投票

在 Swift 4 中:

let ref = Database.database().reference()
let uid = Auth.auth().currentUser?.uid
let userRef = ref.child("users").child(uid!)
var myImageView = UIImageView()

userRef.getDocument { (document, error) in
if let document = document, document.exists {
    let myData = document.data()
    if let profileURL = myData["profileURL"] as? String {
        let storageRef = Storage.storage().reference(forURL: profileURL)
        myImageView.sd_setImage(with: storageRef, 
        placeholderImage:UIImage(named: "placeholder.png"))
    }
    else {
        print("profileURL is nil")
    }
} 
else {
    print("Document does not exist")
}

}

© www.soinside.com 2019 - 2024. All rights reserved.