How to deal with Could not cast Appdelegate to FIRMessagingDelegate - ios

if #available(iOS 10.0, *)
{
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
// For iOS 10 data message (sent via FCM
Messaging.messaging().delegate = (self as! MessagingDelegate)
Couldn't cast value from Appdelegate to FIRMessagingDelegate

You need conform to the protocol in class line
class AppDelegate: UIResponder, UIApplicationDelegate,FIRMessagingDelegate {
as this cast (self as! MessagingDelegate) will crash , then replace it with
Messaging.messaging().delegate = self

Related

How to access AppDelegate object and call method from other SwiftUI views

I am working with the SwiftUI app and I configured my Push Notification setup in AppDelegate and it's working fine like below:
Messaging.messaging().delegate = self
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
Now I have to move this code from app launch to TabBarView screen where I can request for permission once login success.
So for that, I have created func in AppDelegate file like this:
func enablePushNotification() {
let application = UIApplication.shared
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
}
and calling it from TabBarView() like this:
init() {
print("TabBar Init called")
configurePushNotification()
}
func configurePushNotification() {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
appDelegate.enablePushNotification()
}
}
But I am not able to get the AppDelegate object here and It's unable to call appDelegate method from TabBarView().
Any suggestion here why I am not able to get the AppDelegate object or is there any other way to get it?

Ask for notification in ViewController.

Currently, my app asks users for notification permission right on initial opening, how do I ask them when they click a specific button and how do I run the registerForRemoteNotifications in that ViewController when they click yes. The following is my AppDelegate where its currently promoting users.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
UIApplication.shared.applicationIconBadgeNumber = 0
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
Put this inside a ViewController and run the function inside an action or the ViewDidLoad.
func registerForRemoteNotification() {
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
if error == nil{
UIApplication.shared.registerForRemoteNotifications()
}
}
}
else {
UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
UIApplication.shared.registerForRemoteNotifications()
}
}
You need to set it in your completionHandler.
This line: UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
Should be:
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { granted, error in
if granted {
application.registerForRemoteNotifications()
// Do other things after user has been granted authorization
}
})

how to place Notification Authorization Request for FCM outside AppDelegate?

when we want to implement Firebase Cloud Messaging, we first have to ask permission for notification to the user. from Firebase Documentation they recommend this lines of codes to be implemented in Appdelegate on didFinishLaunchingWithOptions like below :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
return true
}
but if place those codes in appDelegate, the pop up alert to ask permission will show up immediately after the user open up my app.but I want to show the alert in the certain View Controller.
if I move those code to a VC, then the application is not available, since the application comes from didFinishLaunchingWithOptions. and then the messagingDelegate ... I am not sure. could you please help me to rewrite those codes but if it is not in AppDelegate?
Add a Class
import Foundation
import FirebaseMessaging
import FirebaseInstanceID
import UserNotifications
class Notifications {
private init() { }
static let shared = Notifications()
func requestNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (isAuthorized, error) in
if error != nil {
print(error as Any)
return
} else {
print("set up successfully")
// Completion Code Here:
}
}
}
}
Add to your prefered VC
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Notifications.shared.requestNotifications()
}
I was testing on a iOS 10.3.3 device and it didn't register until I set the delegate of the UNUserNotificationCenter to UIApplication.shared.delegate as? UNUserNotificationCenterDelegate implementing delegate in the AppDelegate as an empty delegate. But it didn't work implementing an empty delegate in the current view controller.
AppDelegate.swift:
extension AppDelegate: UNUserNotificationCenterDelegate { }
So here's the method in my view controller:
private func registerPushNotifications() {
Messaging.messaging().delegate = self
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = UIApplication.shared.delegate as? UNUserNotificationCenterDelegate
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {granted, _ in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
})
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared.registerUserNotificationSettings(settings)
UIApplication.shared.registerForRemoteNotifications()
}
}
Of course you have to leave FirebaseApp.configure() in didFinishLaunchingWithOptions method.
Later edit: You might get a warning about calling registerForRemoteNotifications() from the main thread, so I adjusted the code to do that.

FCM push notification error in swift 2.0

if #available(iOS 10.0, *) {
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in }
)
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
// For iOS 10 data message (sent via FCM)
FIRMessaging.messaging().remoteMessageDelegate = self //ERROR THIS LINE
}
else {
let settings: UIUserNotificationSettings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
Getting error when set the delegate to self.
"FIRMessing has no member remoteMessageDelegate"
It looks like the Google documentation is out of date.
Please run the following commands in your terminal:
pod repo update
Then go to your project folder and run
pod update
(please mark this as the solution if this helped you)
Try this:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, FIRMessagingDelegate{
}
//MARK: FIRMessaging Delegate
func applicationReceivedRemoteMessage(remoteMessage: FIRMessagingRemoteMessage){
}

registerUserNotificationSettings is not firing delegates and push notification not working my project

I did all the procedures written in the documentation. That is my code. When I added breakpoint, this delegates was not called.
private func pushNotificationHandler(_ application: UIApplication){
FirebaseApp.configure()
Messaging.messaging().delegate = self
if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in })
application.registerForRemoteNotifications()
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
UIApplication.shared.applicationIconBadgeNumber = 0
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
// program never come here
print(deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
// program never come here
print(error)
}
edit: tested in iphone 6 is working done, but iPhone 11 pro max , iPhone XS Max And iPhone 7 are the same problem.
i think you need to add
FirebaseApp.configure()
Messaging.messaging().delegate = self
in Appdelegate->didFinishLaunchingWithOptions
I solved the problem. The internet connection of the phone cannot connect with apple push servers. After 10 hours, I changed the DNS and solved the problem.

Resources