Firebase and iOS

How to Upload Images to Cloud Storage for Firebase with Swift

Myrick Chow
Firebase Developers
6 min readApr 11, 2021

--

Cloud Storage for Firebase is a great place for us to store users’ files. Uploading and downloading files to and from Cloud Storage is very simple and straightforward: Firebase provides a set of SDK for iOS, Android, Web, C++ and Unity developers to manage Cloud Storage for Firebase in an easy way. And it is easy for developers to restrict the access right to each file with Firebase Security Rules.

Below is a simple illustration of what we are going to build in this tutorial:

Getting Started

Please follow the official documentation to set up your Firebase project and enable Cloud Storage for Firebase using the Firebase console. Make sure you upgrade to the Blaze plan if your storage requirements exceed the 5GB free quota.

Building the UI

UIImagePickerController is a special kind of UIViewController which allows users to select photos or video clips from camera or album source. For demonstration purposes, I set the sourceType to photoLibrary and mediaTypes to image file only. You can change them to other values for your own purpose, e.g. recording a video clip from a camera source.

UIImagePickerController for selecting images from the user’s album

We then need to implement both the UIImagePickerControllerDelegate and UINavigationControllerDelegate to handle the selected file information (file URL). We can then initiate uploading the file to Cloud Storage for Firebase on line 24.

To learn more aboutUIImagePickerViewController, check out the following article:

Uploading Files to Cloud Storage for Firebase

We can divide the above codes into the below sessions:

  1. Line 6–7: Construct a unique file name to the file stored in Cloud Storage for Firebase. Please note that new files will overwrite the original file if the file names are the same.
  2. Line 9: Create a Storage reference with the filename. We can also store it inside a “folder” if you like. “Folder” is only a human-readable term, as there are no directory in Cloud Storage. Files have no hierarchical relationship.
    Reference: Cloud Storage Object Name Documentation
  3. Line 10–26: Upload the file data along with its metadata. After a successful upload, we can fetch the download URL of the uploaded image and then fetch it with any image loader, e.g. Kingfisher.

Handling errors

There could be errors during uploading files to Cloud Storage for Firebase at both server and client sides. We can handle the errors with the observe function. Here are some common errors:

  1. Violation of Cloud Storage Security Rules
    Firebase server can reject any read and write operations based on the security rules. For example, the only logged-in user may upload files:

2. Network connection error
Network stability is sometimes an issue on the client-side. For example, during underground transportation or inside a lift.

3. Free quota is exceeded
According to the Firebase pricing, there is a 5GB free quota for projects on the Spark Plan. The project owner has to upgrade to Blaze Plan in order to have larger storage.

4. Cancelled by user

Singleton Nature —✖️ UIViewController Lifecycle

Uploading a file to the Cloud server can be a long-running operation depending on the user’s network condition (and the file size). Sometimes, users probably like to navigate to another screen during the uploading task.

🤔 Do you think users must stay on the upload screen until the upload has finished?

The answer is “no”.

SDK has taken care of this situation by using a singleton pattern. The Storage instance returned from Storage.storage() is a singleton, which lives as long as the app lives. Therefore, the uploading task is still running in the background even the user has exited the page for uploading files.

Your 2nd question probably is “How can we handle the event (completion or error) of the uploading task when the user has navigate to a different screen?

One way to do this is to use the Notification center:

At the callback of the putData, we can enclose the storageMetaData and error into a dictionary, and then pass it to Notification observers through userInfo field.

Finally, we can add a Notification observer at the base UIViewController such that all UIViewControllers in the app can share the same logic. storageMetaData and error can be retrieved back from the userInfo of the Notification object, see line 11–12.

App Lifecycle — Auto pause and resume

After discussing the UIViewController lifecycle topic, let’s focus on the app lifecycle. What will happen when users send the app to the background during uploading files? Will the task be resumed automatically after the app is active in the foreground? The answer is “the SDK will take care of this, too!

In iOS, there are three application states:

  1. active — the app is in the foreground
  2. inactive — the app is also in the foreground but cannot receive any events from the user. This is the case when you receive a call or an SMS, for example.
  3. background — the app totally disappears from the screen

According to Apple’s documentation, each app can have around 30s to carry out its operations when it is sent to the background. The length of time can be shorter depending on the device situation. In other words, the Firebase SDK can still continue the uploading task at this 30s stage but it is forced to stop by the system after that. Any incomplete upload tasks will be resumed when the app becomes active again. See the above graph for a better illustration.

What about caching?

If you have used Cloud Firestore before, you were probably amazed by the local cache system. Even when the device is offline Firestore can save the user’s new data at the local database first and reupload them to the server automatically once connectivity resumes.

However, Cloud Storage for Firebase does not have a similar feature. Once the file cannot be uploaded due to a network issue, we have to upload it later again manually.

Summary

Cloud Storage for Firebase is a cloud tool for developers to store files and fetch them at the client-side with the help of a user-friendly SDK.

The SDK uses a singleton pattern to tackle the UIViewController lifecycle issue. The uploading task can continue even when the UIViewController is dismissed.

SDK has handled the app lifecycle issue for developers. It can resume the paused uploading task right after the app becomes active in the foreground.

However, SDK does not have a local cache system and users have to execute the uploading task manually.

--

--

Myrick Chow
Firebase Developers

Mobile Lead @REAL Messenger Inc. https://real.co Focus on Android & iOS Native programming.