I would like to generate notification to specific moment in my swift application but I got this message witch indicate me that apns token is not specified. however I generate the certificate from apple developper and I download it to inject it in firebase settings.
I'm currently running this application on the simulator.
By the way the code is running on my kotlin side perfectly from the simulator.
this is my code from Xcode this class is used to manage notifications :
import Foundation
import UIKit
import Firebase
import FirebaseMessaging
import UserNotifications
class PushNotificationManager: NSObject, MessagingDelegate, UNUserNotificationCenterDelegate {
private lazy var currentController: UIViewController? = {
if let window = UIApplication.shared.windows.first, let rootViewController = window.rootViewController {
var currentController = rootViewController
while let presentedController = currentController.presentedViewController {
currentController = presentedController
}
return currentController
}
return nil
}()
private var notificationDetails: FirebaseNotificationAPI?
func registerForPushNotifications() {
if #available(iOS 10.0, *) {
// For iOS 10 and later, display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(options: authOptions) { granted, error in
if granted {
print("Notification authorization granted")
// Register for remote notifications after authorization is granted
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
if let error = error {
print("Notification authorization error: \(error.localizedDescription)")
}
}
}
Messaging.messaging().delegate = self
} else {
// For older iOS versions, register for user notifications
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
UIApplication.shared.registerForRemoteNotifications()
}
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("FCM Token: \(fcmToken as Any)")
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
handleNotificationTap(userInfo: response.notification.request.content.userInfo)
completionHandler()
}
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
handleNotificationTap(userInfo: notification.request.content.userInfo)
completionHandler([.badge, .sound, .alert])
}
private func handleNotificationTap(userInfo: [AnyHashable: Any]) {
guard let data = userInfo as? [String: Any], let notificationDetails = FirebaseNotificationAPI.deserialize(from: data) else { return }
self.notificationDetails = notificationDetails
if let currentController = currentController {
let alertController = UIAlertController(title: notificationDetails.aps?.alert?.title, message: notificationDetails.aps?.alert?.body, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
currentController.present(alertController, animated: true, completion: nil)
}
}
}
This is my main class :
import SwiftUI
import Firebase
import UserNotifications
import FirebaseMessaging
import FirebaseCore
import FirebaseFirestore
import FirebaseAuth
@main
struct ML2V_IOSApp: App {
@StateObject var viewModel = AuthViewModel()
let pushNotificationManager = PushNotificationManager()
init(){
FirebaseApp.configure()
FirebaseConfiguration.shared.setLoggerLevel(.max)
requestNotificationAuthorization()
pushNotificationManager.registerForPushNotifications()
}
var body: some Scene {
WindowGroup {
ContentRooting().environmentObject(viewModel)
}
}
}
func requestNotificationAuthorization() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("Autorisation pour les notifications accordée")
} else {
if let error = error {
print("Erreur d'autorisation des notifications : \(error.localizedDescription)")
}
}
}
}
This is the moment when I want to inject fcm to firebase to use it later :
import Foundation
import Firebase
import FirebaseFirestoreSwift
import FirebaseMessaging
protocol AuthenticationFormProtocol{
var formIsValid: Bool {
get
}
}
@MainActor
class AuthViewModel: ObservableObject{
@Published var userSession: FirebaseAuth.User?
@Published var currentUser: User?
init(){
self.userSession = Auth.auth().currentUser
Task{
await getUser()
}
}
//Fonction pour la connexion de l'utilisateur
func connexionUser(whithEmail email: String, password: String) async throws {
do{
let result = try await Auth.auth().signIn(withEmail: email, password: password)
self.userSession = result.user
await getUser()
}catch{
print("DEBUG : Impossible de connecter l'utilisateur")
}
}
//Fonction pour l'inscription de l'application
func inscriptionUser(withEmail email: String, password: String, prenom: String, nom: String, role: String, societe: String, tel: String, date: Date) async throws{
do{
let result = try await Auth.auth().createUser(withEmail: email, password: password)
self.userSession = result.user
print("DEBUG : uid inscription \(result.user.uid)")
let user = User(id: result.user.uid, fcm: "", prenom: prenom, nom: nom, email: email, role: role, societe: societe, telephone: tel, date_inscription: Date())
let userDictionary: [String: Any] = [
"prenom": prenom,
"nom": nom,
"role": role,
"societe": societe,
"telephone": tel,
"date_inscription": date,
"fcm": ""
]
try await Firestore.firestore().collection("users").document(result.user.uid).setData(userDictionary)
await getUser()
}catch{
print("DEBUG: Impossible de créer l'utilisateur\(error.localizedDescription)")
}
}
//Permet de récupérer toutes les informations de mon utilisateur actuel
func getUser() async{
guard let uid = Auth.auth().currentUser?.uid else{return}
guard let email = Auth.auth().currentUser?.email else{return}
if let useruid = Auth.auth().currentUser?.uid, let token = Messaging.messaging().fcmToken {
let db = Firestore.firestore()
let userDocRef = db.collection("users").document(useruid)
do {
try await userDocRef.setData(["fcm": token], merge: true)
print("FCM token updated successfully.")
} catch {
print("Error updating FCM token: \(error.localizedDescription)")
}
} else {
print("FCM token is nil.")
}
guard let snapshot = try? await Firestore.firestore().collection("users").document(uid).getDocument() else{ return }
var snapshotData = snapshot.data() ?? [:]
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "d MMMM yyyy à HH:ss ZZZZZ"
snapshotData["email"] = email
snapshotData["id"] = uid
if let dateString = snapshotData["date_inscription"] as? String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMMM yyyy 'à' HH:mm:ss 'UTC'Z"
dateFormatter.locale = Locale(identifier: "fr_FR")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC+0200")
if let date = dateFormatter.date(from: dateString) {
snapshotData["date_inscription"] = date
}
}
//print(snapshotData)
self.currentUser = try? Firestore.Decoder().decode(User.self, from: snapshotData)
}
//Deconnexion de l'utilisateur
func deconnexion(){
do{
try Auth.auth().signOut()
self.userSession = nil
self.currentUser = nil
}catch{
print("DEBUG : Impossible de deconnecter l'utilisateur")
}
}
func updateEmail(email: String) async throws{
guard let user = Auth.auth().currentUser else{return}
try await user.updateEmail(to: email)
await getUser()
}
func updatePassword(password: String) async throws{
guard let user = Auth.auth().currentUser else{return}
try await user.updatePassword(to: password)
await getUser()
}
func updatePhone(tel: String) async throws{
guard let uid = Auth.auth().currentUser?.uid else{return}
let updatedElement: [String: Any] = [
"telephone": tel
]
try? await Firestore.firestore().collection("users").document(uid).setData(updatedElement, merge: true)
await getUser()
}
func convertTimestampToString(_ timestamp: Timestamp) -> String {
let date = timestamp.dateValue()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMMM yyyy 'à' HH:mm:ss 'UTC'Z"
dateFormatter.locale = Locale(identifier: "fr_FR")
dateFormatter.timeZone = TimeZone(abbreviation: "UTC+2")
return dateFormatter.string(from: date)
}
}
My fcm return alway nil. I don't know why. I'm knew on swift development if somebody can help me I will be thankful.
answer here thank to all : https://github.com/firebase/quickstart-ios/blob/master/messaging/MessagingExampleSwift/AppDelegate.swift
not possible for iOS simulator for the moment