Reputation: 67
So on the view controller that the user uploads the video to Firebase, I have a UIProgressView
and UILabel
that observe the progress of the upload task. This works perfectly fine. The problem, is when I leave the view controller. The UIProgressView
is reset, and I don't know how to regain that information to resume observing the progress since it's all asynchronous. Is there any way that I can stop the view controller from reloading once the user has left that controller so that the progress view and label remain unchanged and not reloaded? Here is some code for reference (the function responsible for observing the task):
func uploadVideo(videoURL: URL)
{
let storage = Storage.storage()
let storageRef = storage.reference()
let videoRef = storageRef.child("rPosts/\(uid!)/\(fileID).mov")
let metadata = StorageMetadata()
metadata.contentType = "video/quicktime"
var videoData: Data = Data()
do
{
videoData = try Data(contentsOf: videoURL)
}
catch
{
print(error.localizedDescription)
return
}
let taskReference = videoRef.putData(videoData, metadata: metadata)
{ (metaData, error) in
guard error == nil else
{
self.errorLabel.text = error!.localizedDescription
return
}
}
taskReference.observe(.progress)
{ [weak self] (snapshot) in
guard let progress = snapshot.progress?.fractionCompleted else { return }
self?.progressView.progress = Float(progress)
self?.progressLabel.text = "\(round(100 * Float(progress)))% (2/2)"
if progress == 1
{
self!.progressLabel.text = "Upload Successful!"
self!.progressLabel.textColor = .black
self!.progressView.progress = 0
}
}
}
How can I access taskReference
?
Upvotes: 0
Views: 250
Reputation: 773
You just need a better approach to handle this. You should not put this upload related stuff inside your view controller.
You can move upload related stuff to some separate file like below:
protocol StorageManagerObserver: AnyObject {
func storageManager(_ storageManager: StorageManager, didProgressUpload fractionCompleted: Float)
func storageManager(_ storageManager: StorageManager, didFailWithError error: Error)
}
class StorageManager: NSObject {
static var shared = StorageManager()
private var observers: [StorageManagerObserver] = []
let storage = Storage.storage()
deinit {
observers.removeAll()
}
func addObserver(_ observer: StorageManagerObserver) {
if observers.contains(where: { $0 === observer }) == false {
observers.append(observer)
}
}
func removeObserver(_ observer: StorageManagerObserver) {
guard let index = self.observers.firstIndex(where: { $0 === observer }) else {
return
}
self.observers.remove(at: index)
}
func uploadVideo(videoURL: URL, uid: Int?, fileID: Int) {
let storageRef = storage.reference()
let videoRef = storageRef.child("rPosts/\(uid!)/\(fileID).mov")
let metadata = StorageMetadata()
metadata.contentType = "video/quicktime"
var videoData: Data = Data()
do {
videoData = try Data(contentsOf: videoURL)
}
catch {
print(error.localizedDescription)
return
}
let taskReference = videoRef.putData(videoData, metadata: metadata) { [weak self] (metaData, error) in
guard let self = self else { return }
guard let someError = error else { return }
for anObserver in self.observers {
anObserver.storageManager(self, didFailWithError: someError)
}
}
taskReference.observe(.progress) { [weak self] (snapshot) in
guard let self = self else { return }
guard let progress = snapshot.progress?.fractionCompleted else { return }
for anObserver in observers {
anObserver.storageManager(self, didProgressUpload: progress)
}
}
}
}
I've made this StorageManager singleton, you can have some other approach as per you need (as we need to keep it alive until its done). Now, you use this to any view controller, like this:
class YourViewController: UIViewController {
@IBOutlet weak var errorLabel: UILabel!
@IBOutlet weak var progressLabel: UILabel!
@IBOutlet weak var progressView: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
StorageManager.shared.addObserver(self)
}
deinit {
StorageManager.shared.removeObserver(self)
}
}
extension YourViewController: StorageManagerObserver {
func storageManager(_ storageManager: StorageManager, didProgressUpload fractionCompleted: Float) {
self.progressView.progress = fractionCompleted
self.progressLabel.text = "\(round(100 * fractionCompleted))% (2/2)"
if fractionCompleted == 1 {
self.progressLabel.text = "Upload Successful!"
self.progressLabel.textColor = .black
self.progressView.progress = 0
}
}
func storageManager(_ storageManager: StorageManager, didFailWithError error: Error) {
self.errorLabel.text = error.localizedDescription
}
}
Upvotes: 2