Bird
Raised Fist0
iOS Swiftmobile~20 mins

Cloud Storage in iOS Swift - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Cloud Storage Upload
This screen lets users select a photo from their device and upload it to cloud storage. It shows upload progress and confirms when upload is done.
Target UI
-------------------------
| Cloud Storage Upload  |
-------------------------
| [Select Photo]        |
|                       |
|                       |
| Upload Progress: 0%   |
|                       |
| [Upload]              |
-------------------------
Add a button labeled 'Select Photo' that opens the photo picker.
Show the selected photo as a small preview below the button.
Add an 'Upload' button that uploads the selected photo to cloud storage.
Display upload progress as a percentage while uploading.
Show a confirmation message when upload completes successfully.
Handle case when no photo is selected by disabling the Upload button.
Starter Code
iOS Swift
import SwiftUI
import PhotosUI

struct CloudStorageUploadView: View {
    @State private var selectedImage: UIImage? = nil
    @State private var isUploading = false
    @State private var uploadProgress: Double = 0.0
    @State private var showConfirmation = false
    @State private var isPickerPresented = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Cloud Storage Upload")
                .font(.title)
                .padding()

            Button("Select Photo") {
                // TODO: Present photo picker
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)

            // TODO: Show selected image preview here

            Text("Upload Progress: \(Int(uploadProgress * 100))%")

            Button("Upload") {
                // TODO: Upload selected image
            }
            .padding()
            .background(selectedImage == nil || isUploading ? Color.gray : Color.green)
            .foregroundColor(.white)
            .cornerRadius(8)
            .disabled(selectedImage == nil || isUploading)

            if showConfirmation {
                Text("Upload completed successfully!")
                    .foregroundColor(.green)
            }

            Spacer()
        }
        .padding()
    }
}
Task 1
Task 2
Task 3
Task 4
Task 5
Solution
iOS Swift
import SwiftUI
import PhotosUI

struct CloudStorageUploadView: View {
    @State private var selectedImage: UIImage? = nil
    @State private var isUploading = false
    @State private var uploadProgress: Double = 0.0
    @State private var showConfirmation = false
    @State private var isPickerPresented = false

    var body: some View {
        VStack(spacing: 20) {
            Text("Cloud Storage Upload")
                .font(.title)
                .padding()

            Button("Select Photo") {
                isPickerPresented = true
                showConfirmation = false
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
            .sheet(isPresented: $isPickerPresented) {
                PhotoPicker(selectedImage: $selectedImage)
            }

            if let image = selectedImage {
                Image(uiImage: image)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 150, height: 150)
                    .cornerRadius(8)
                    .shadow(radius: 5)
            }

            Text("Upload Progress: \(Int(uploadProgress * 100))%")

            Button("Upload") {
                startUpload()
            }
            .padding()
            .background(selectedImage == nil || isUploading ? Color.gray : Color.green)
            .foregroundColor(.white)
            .cornerRadius(8)
            .disabled(selectedImage == nil || isUploading)

            if showConfirmation {
                Text("Upload completed successfully!")
                    .foregroundColor(.green)
            }

            Spacer()
        }
        .padding()
    }

    func startUpload() {
        guard selectedImage != nil else { return }
        isUploading = true
        uploadProgress = 0.0
        showConfirmation = false

        // Simulate upload with timer
        Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
            uploadProgress += 0.05
            if uploadProgress >= 1.0 {
                timer.invalidate()
                isUploading = false
                showConfirmation = true
            }
        }
    }
}

struct PhotoPicker: UIViewControllerRepresentable {
    @Binding var selectedImage: UIImage?

    func makeUIViewController(context: Context) -> PHPickerViewController {
        var config = PHPickerConfiguration()
        config.filter = .images
        config.selectionLimit = 1
        let picker = PHPickerViewController(configuration: config)
        picker.delegate = context.coordinator
        return picker
    }

    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}

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

    class Coordinator: NSObject, PHPickerViewControllerDelegate {
        let parent: PhotoPicker

        init(_ parent: PhotoPicker) {
            self.parent = parent
        }

        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            picker.dismiss(animated: true)
            guard let provider = results.first?.itemProvider else { return }
            if provider.canLoadObject(ofClass: UIImage.self) {
                provider.loadObject(ofClass: UIImage.self) { image, _ in
                    DispatchQueue.main.async {
                        self.parent.selectedImage = image as? UIImage
                    }
                }
            }
        }
    }
}

This solution uses SwiftUI with PHPickerViewController to let users pick a photo from their device. The selected photo is shown as a preview image below the Select Photo button.

The Upload button is disabled if no photo is selected or if an upload is in progress. When Upload is tapped, a timer simulates upload progress by increasing a progress value every 0.1 seconds. The progress percentage is shown as text.

When upload completes, a confirmation message appears. The photo picker is presented as a sheet. This approach keeps UI responsive and simple for beginners.

Final Result
Completed Screen
-------------------------
| Cloud Storage Upload  |
-------------------------
| [Select Photo]        |
|                       |
|  [Image Preview]      |
| Upload Progress: 75%  |
|                       |
| [Upload]              |
|                       |
| Upload completed      |
| successfully!         |
-------------------------
Tapping 'Select Photo' opens the photo picker to choose an image.
Selected image appears as a preview below the button.
Upload button becomes enabled after photo selection.
Tapping 'Upload' starts upload simulation and updates progress text.
When upload finishes, a success message is shown below the Upload button.
Stretch Goal
Add a cancel button to stop the upload in progress.
💡 Hint
Use a @State variable to track the Timer and call invalidate() to stop it when cancel is tapped.

Practice

(1/5)
1.

What is the main purpose of Cloud Storage in an iOS app?

easy
A. To create user interface elements
B. To store app settings locally on the device
C. To save files online for easy access and sharing
D. To manage app navigation flow

Solution

  1. Step 1: Understand Cloud Storage role

    Cloud Storage is designed to save files online so users can access and share them easily.
  2. Step 2: Compare options

    Options B, C, and D describe other app functions unrelated to Cloud Storage.
  3. Final Answer:

    To save files online for easy access and sharing -> Option C
  4. Quick Check:

    Cloud Storage = Online file saving [OK]
Hint: Cloud Storage means saving files online, not local data [OK]
Common Mistakes:
  • Confusing Cloud Storage with local storage
  • Thinking it manages UI or navigation
  • Assuming it stores app settings only
2.

Which of the following is the correct way to create a reference to a file named image.png in Firebase Cloud Storage using Swift?

let storage = Storage.storage()
let storageRef = ...
easy
A. storageRef = storage.child("image.png")
B. storageRef = storage.reference().child("image.png")
C. storageRef = Storage.reference("image.png")
D. storageRef = storage.reference("image.png")

Solution

  1. Step 1: Recall Firebase Storage syntax

    To get a reference, use storage.reference() then child("filename") to point to the file.
  2. Step 2: Check each option

    storageRef = storage.reference().child("image.png") correctly chains reference() and child(). Options B, C, and D use incorrect method calls or syntax.
  3. Final Answer:

    storageRef = storage.reference().child("image.png") -> Option B
  4. Quick Check:

    Use reference().child() to get file reference [OK]
Hint: Use reference().child("filename") to get file reference [OK]
Common Mistakes:
  • Calling child() directly on storage
  • Using Storage.reference() instead of storage.reference()
  • Passing filename directly to reference()
3.

What will be printed if the following Swift code successfully uploads a file to Firebase Storage?

let storageRef = Storage.storage().reference().child("file.txt")
let localFile = URL(fileURLWithPath: "/path/to/file.txt")
storageRef.putFile(from: localFile, metadata: nil) { metadata, error in
  if let error = error {
    print("Upload failed: \(error.localizedDescription)")
  } else {
    print("Upload succeeded")
  }
}
medium
A. Upload succeeded
B. Upload failed: File not found
C. Upload failed: Network error
D. No output

Solution

  1. Step 1: Analyze the completion handler

    The closure checks if error is nil; if so, it prints "Upload succeeded".
  2. Step 2: Given successful upload

    Since upload is successful, error is nil, so the else block runs printing "Upload succeeded".
  3. Final Answer:

    Upload succeeded -> Option A
  4. Quick Check:

    Success means error is nil, print "Upload succeeded" [OK]
Hint: If error is nil, upload succeeded message prints [OK]
Common Mistakes:
  • Assuming error is always non-nil
  • Confusing success and failure blocks
  • Ignoring the asynchronous completion handler
4.

Identify the error in this Swift code snippet for uploading a file to Firebase Storage:

let storageRef = Storage.storage().reference().child("doc.pdf")
let fileURL = URL(string: "/documents/doc.pdf")!
storageRef.putFile(from: fileURL, metadata: nil) { metadata, error in
  if error != nil {
    print("Upload error")
  } else {
    print("Upload complete")
  }
}
medium
A. Using URL(string:) instead of URL(fileURLWithPath:)
B. Missing metadata parameter in putFile
C. Incorrect child path syntax
D. No completion handler provided

Solution

  1. Step 1: Check URL creation method

    URL(string:) is for web URLs; local file paths need URL(fileURLWithPath:).
  2. Step 2: Identify impact

    Using URL(string:) with a local path returns nil or incorrect URL, causing upload failure.
  3. Final Answer:

    Using URL(string:) instead of URL(fileURLWithPath:) -> Option A
  4. Quick Check:

    Local file URLs need URL(fileURLWithPath:) [OK]
Hint: Use URL(fileURLWithPath:) for local file paths [OK]
Common Mistakes:
  • Using URL(string:) for local files
  • Forgetting to unwrap optional URLs safely
  • Ignoring completion handler errors
5.

You want to upload multiple images to Firebase Cloud Storage and keep track of their download URLs for later use. Which approach correctly handles this in Swift?

let images = [URL(fileURLWithPath: "/img1.png"), URL(fileURLWithPath: "/img2.png")]
var downloadURLs: [URL] = []
for imageURL in images {
  let ref = Storage.storage().reference().child(imageURL.lastPathComponent)
  ref.putFile(from: imageURL, metadata: nil) { metadata, error in
    if error == nil {
      ref.downloadURL { url, error in
        if let url = url {
          downloadURLs.append(url)
        }
      }
    }
  }
}
print(downloadURLs)
hard
A. The code will cause a syntax error due to missing await
B. This code correctly prints all download URLs immediately
C. The code uploads files but does not get download URLs
D. This code may print an empty array because uploads are asynchronous

Solution

  1. Step 1: Understand asynchronous behavior

    Uploads and downloadURL calls run asynchronously, so print(downloadURLs) runs before completion.
  2. Step 2: Effect on printed output

    Because of async calls, downloadURLs is likely empty when printed immediately after the loop.
  3. Final Answer:

    This code may print an empty array because uploads are asynchronous -> Option D
  4. Quick Check:

    Async uploads delay URL collection, print runs too early [OK]
Hint: Async calls need completion before using results [OK]
Common Mistakes:
  • Expecting synchronous behavior from async uploads
  • Printing results before upload completion
  • Not using dispatch groups or async-await to wait
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard