Próbuję obserwować postępy podczas przesyłania obrazu do magazynu ForBase. Postęp jest aktualizowany w konsoli, jednak mój Progressview nie aktualizuje. Wszystko inne wydaje się działać zgodnie z oczekiwaniami. Jakiś pomysł, co robię źle?

class UserManager: ObservableObject  {

@Published var taskProgress: Float = 0.0
let user = Auth.auth().currentUser



func uploadProfilePicture(image: UIImage) {
    
    let uploadRef = FirebaseReferenceManager.storage.reference(withPath: "profile/\(user!.uid)")
    
    guard let imageData = image.jpegData(compressionQuality: 0.75) else {
        return
    }
    
    let uploadMetaData = StorageMetadata.init()
    uploadMetaData.contentType = "image/jpeg"
    
    let taskReference = uploadRef.putData(imageData, metadata: uploadMetaData) { (downloadMetaData, error) in
        if let error = error {
            print(error.localizedDescription)
            return
        } else {
            print("Successfully Uploaded Profile Picture to Firebase Storage")
            let downloadRef = FirebaseReferenceManager.storage.reference(withPath: "profile/\(self.user!.uid)")
            downloadRef.downloadURL { (url, error) in
                
                if let error = error {
                    print(error.localizedDescription)
                    return
                }
                
                FirebaseReferenceManager.root.collection(FirebaseKeys.CollectionPath.users).document(self.user!.uid).setData([FirebaseKeys.UsersFieldPath.photoURL : url!.absoluteString], merge: true)
            }
            
            

        }
    }

    
    taskReference.observe(.progress) { [weak self] (snapshot) in
        DispatchQueue.main.async {
            guard let pctThere = snapshot.progress?.fractionCompleted else {return}
            print(pctThere)
            self?.taskProgress = Float(pctThere)
        }

    }
    taskReference.resume()
    

}

}

Moim zdaniem umieściłem

@EnvironmentObject var userManager: UserManager

ProgressView(value: userManager.taskProgress).progressViewStyle(LinearProgressViewStyle())

Oto jak klasa jest inicjowana:

struct SwiftUIView: View {
@StateObject var userManager = UserManager()

var body: some View {
    
    TabView {
        
        HomeView().tabItem {
            Image("home")
            Text("Home")
            
        }
        

        SearchView().tabItem {
            Image("search")
            Text("Search")
            
        }
        
        DiscoverView().tabItem {
            Image("discover")
            Text("Discover")
            
        }
        
        OrdersView().tabItem {
            Image("calendar")
            Text("Orders")
            
        }
        
        InboxView().tabItem {
            Image("inbox")
            Text("Inbox")
            
        }
    }
    .environmentObject(userManager)
}

}

A potem przekazuję go głębiej w hierarchii

    @EnvironmentObject var userManager: UserManager

Oto miejsce, gdzie nazywa się UploadProfilPicture:

struct ImagePicker: UIViewControllerRepresentable {

var sourceType: UIImagePickerController.SourceType = .photoLibrary

@Binding var selectedImage: UIImage
@Environment(\.presentationMode) private var presentationMode


func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
    
    let imagePicker = UIImagePickerController()
    imagePicker.delegate = context.coordinator
    imagePicker.allowsEditing = true
    imagePicker.sourceType = sourceType
    
    return imagePicker
}

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}


func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {

}


class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
 
    let parent: ImagePicker
    @ObservedObject private var userManager = UserManager()

 
    init(_ parent: ImagePicker) {
        self.parent = parent
    }
 
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
 
        if let image = info[.editedImage] as? UIImage {
            parent.selectedImage = image
            userManager.uploadProfilePicture(image: image)
        }
        

        parent.presentationMode.wrappedValue.dismiss()
    }
}

}

1
devOP1 15 kwiecień 2021, 16:05

1 odpowiedź

Najlepsza odpowiedź

Od komentarzy wywnioskowaliśmy, że była inna instancja UserManager. Byłby to przykładem, jak przekazać to samo instancję do Coordinator (przy założeniu, że ImagePicker istnieje w środowisku, w którym jest dostępna @EnvironmentObject var userManager: UserManager).

struct ImagePicker: UIViewControllerRepresentable {
    
    var sourceType: UIImagePickerController.SourceType = .photoLibrary
    
    @Binding var selectedImage: UIImage
    @Environment(\.presentationMode) private var presentationMode
    @EnvironmentObject private var userManager: UserManager //<-- Here
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = context.coordinator
        imagePicker.allowsEditing = true
        imagePicker.sourceType = sourceType
        
        return imagePicker
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self, userManager: userManager)  //<-- Here
    }
    
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
        
    }
    
    
    class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        
        let parent: ImagePicker
        let userManager: UserManager
        
        init(_ parent: ImagePicker, userManager: UserManager) {  //<-- Here
            self.parent = parent
            self.userManager = userManager  //<-- Here
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            
            if let image = info[.editedImage] as? UIImage {
                parent.selectedImage = image
                userManager.uploadProfilePicture(image: image)
            }
            
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
}
1
jnpdx 15 kwiecień 2021, 17:47