Firebase & iOS Notifications

Notifiche Push con Firebase Cloud Messaging (FCM) e APNs in SwiftUI: Guida Completa

Le notifiche push sono il canale principale per ingaggiare gli utenti nelle app mobile moderne. Su iOS, l'architettura di recapito passa da APNs (Apple Push Notification service), ma l'utilizzo di Firebase Cloud Messaging (FCM) offre una gestione semplificata per l'invio targeted, la profilazione e la messaggistica cross-platform.

1. Architettura ed Integrazione APNs + FCM

Per collegare Firebase ad APNs è necessario generare una chiave d'attivazione (.p8 Key) nel portale Apple Developer e caricarla nella console Firebase nella sezione Project Settings -> Cloud Messaging indicando il proprio Key ID e Team ID.

2. Configurazione dell'AppDelegate e MessagingDelegate in SwiftUI

Negli ambienti SwiftUI nativi basati sul macro @main, occorre collegare un UIApplicationDelegateAdaptor per intercettare i token APNs ed il ciclo di vita del dispositivo:

import SwiftUI
import FirebaseCore
import FirebaseMessaging
import UserNotifications

class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
    ) -> Bool {
        FirebaseApp.configure()
        
        // Registrazione per notifiche remote
        UNUserNotificationCenter.current().delegate = self
        Messaging.messaging().delegate = self
        
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
            print("Autorizzazione notifiche concessa: \(granted)")
        }
        
        application.registerForRemoteNotifications()
        return true
    }
    
    // Ricezione Token APNs da Apple
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }
    
    // Ricezione Token FCM da Firebase
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        guard let token = fcmToken else { return }
        print("Token FCM aggiornato: \(token)")
        // Inviare il token FCM al server backend / Firestore dell'utente
    }
    
    // Gestione notifica in Foreground
    func userNotificationCenter(
        _ center: UNUserNotificationCenter,
        willPresent notification: UNNotification,
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
    ) {
        completionHandler([.banner, .sound, .badge])
    }
}

@main
struct MyApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

3. Salvare il Token FCM su Cloud Firestore

Una volta ottenuto il token FCM, occorre associarlo all'ID utente autenticato nel database Firestore per poter puntare le notifiche a specifici dispositivi:

import FirebaseFirestore
import FirebaseAuth

func syncFCMTokenToFirestore(fcmToken: String) {
    guard let uid = Auth.auth().currentUser?.uid else { return }
    
    let userRef = Firestore.firestore().collection("users").document(uid)
    userRef.setData([
        "fcmToken": fcmToken,
        "lastUpdated": FieldValue.serverTimestamp(),
        "platform": "ios"
    ], merge: true) { error in
        if let error = error {
            print("Errore nel salvataggio del token FCM: \(error.localizedDescription)")
        } else {
            print("Token FCM sincronizzato con successo.")
        }
    }
}

4. Invio di Notifiche Mirate via Firebase Admin SDK (Node.js)

Sul backend (Cloud Functions o microservizio Node.js), l'invio della notifica tramite Firebase Admin SDK avvenga così:

import * as admin from "firebase-admin";

admin.initializeApp();

async function sendPushToUser(fcmToken: string, title: string, body: string, deepLinkUrl: string) {
  const message: admin.messaging.Message = {
    token: fcmToken,
    notification: {
      title: title,
      body: body,
    },
    data: {
      url: deepLinkUrl,
      type: "chat_message",
    },
    apns: {
      payload: {
        aps: {
          sound: "default",
          badge: 1,
        },
      },
    },
  };

  try {
    const response = await admin.messaging().send(message);
    console.log("Notifica inviata con successo:", response);
  } catch (error) {
    console.error("Errore invio push FCM:", error);
  }
}

Conclusione

Integrare FCM ed APNs con SwiftUI garantisce una gestione flessibile dei token e una sincronizzazione affidabile sia per messaggi broadcast che per notifiche ad personam. Per assistenza sullo sviluppo di notifiche avanzate e rich media extension per le tue app iOS, scrivi a diallooyunus@gmail.com.

Yunus Diallo (DialloDev)

Fondatore di Dywtal Digital a Parma (Italia), sviluppatore iOS con 11+ App sul Mac & App Store. Specializzato in architetture SwiftUI, Firebase e cloud backend scalabili.