Il caricamento di media ad alta risoluzione da un'applicazione iOS verso il cloud richiede due attenzioni fondamentali: **ottimizzazione della dimensione dei file** prima dell'invio e **tracciamento del progresso** per offrire una UX fluida all'utente.
1. Compressione dell'Immagine lato Client in Swift
Inviare direttamente foto da 12 megapixel scattate da un iPhone spreca banda e spazio di archiviazione. Possiamo ridimensionare e comprimere l'immagine via jpegData(compressionQuality:):
import UIKit
func prepareImageForUpload(image: UIImage, maxDimension: CGFloat = 1200, compression: CGFloat = 0.7) -> Data? {
let aspectWidth = maxDimension / image.size.width
let aspectHeight = maxDimension / image.size.height
let aspectRatio = min(aspectWidth, aspectHeight)
var newSize = image.size
if aspectRatio < 1.0 {
newSize = CGSize(width: image.size.width * aspectRatio, height: image.size.height * aspectRatio)
}
let renderer = UIGraphicsImageRenderer(size: newSize)
let resizedImage = renderer.image { _ in
image.draw(in: CGRect(origin: .zero, size: newSize))
}
return resizedImage.jpegData(compressionQuality: compression)
}
2. Gestione UploadTask e Progress Bar in SwiftUI
Firebase Storage fornisce la classe StorageUploadTask che permette di osservare le fasi dell'upload ed aggiornare una variabile @Published in SwiftUI:
import SwiftUI
import FirebaseStorage
class ImageUploadViewModel: ObservableObject {
@Published var uploadProgress: Double = 0.0
@Published var isUploading: Bool = false
@Published var downloadURL: String? = nil
func uploadImage(data: Data, userId: String) {
let storageRef = Storage.storage().reference()
let fileRef = storageRef.child("users/\(userId)/avatar_\(UUID().uuidString).jpg")
let metadata = StorageMetadata()
metadata.contentType = "image/jpeg"
self.isUploading = true
let uploadTask = fileRef.putData(data, metadata: metadata)
// Tracciamento avanzamento
uploadTask.observe(.progress) { [weak self] snapshot in
guard let progress = snapshot.progress else { return }
DispatchQueue.main.async {
self?.uploadProgress = Double(progress.completedUnitCount) / Double(progress.totalUnitCount)
}
}
// Completamento
uploadTask.observe(.success) { [weak self] _ in
fileRef.downloadURL { url, error in
DispatchQueue.main.async {
self?.isUploading = false
self?.downloadURL = url?.absoluteString
}
}
}
}
}
3. Security Rules per Firebase Storage
Assicurati che soltanto l'utente autenticato proprietario della cartella possa scrivere ed eliminare i file:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /users/{userId}/{allPaths=**} {
allow read: if request.auth != null;
allow write: if request.auth != null && request.auth.uid == userId
&& request.resource.size < 5 * 1024 * 1024 // Max 5 MB
&& request.resource.contentType.matches('image/.*');
}
}
}
Conclusione
La compressione preventiva associata al tracciamento in tempo reale assicura un upload veloce ed esente da errori. Per assistenza nell'architettura media per app SwiftUI, scrivi a diallooyunus@gmail.com.