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
}
})
Related
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?
How can the following code that has been deprecated in iOS 10 be used in Swift 4? This application is used to send push notifications using Firebase.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let notificationTypes : UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let notificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(notificationSettings)
return true
}
and
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
// Print message ID.
print("Message ID: \(userInfo["gcm.message_id"]!)")
print(userInfo)
}
Any help is appreciated, thanks.
This is now I do it in my apps where I use Firebase notifications.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
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 })
// For iOS 10 data message (sent via FCM)
Messaging.messaging().remoteMessageDelegate = self
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
FirebaseApp.configure()
}
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.
request authorization for push notifications always return false when app is first loaded even user tap "allow" on dialog.
Here is function for register which is called in didFinishLaunchingWithOptions. At next launch granted is true.
func registerForPushNotifications() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) {
(granted, error) in
print("Permission granted: \(granted)")
guard granted else{return}
self.getNotificationSettings()
}
}
Register for remote notification within didfinishLaunchingWithOptions and make sure registered for remote notification.
application.registerForRemoteNotifications()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
guard granted else{return}
self.getNotificationSettings()
}
application.registerForRemoteNotifications()
return true
}
Add below code in didfinishLaunchingWithOptions method,
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
if granted {
}
}
UNUserNotificationCenter.current().getNotificationSettings(){ (setttings) in
switch setttings.soundSetting{
case .enabled:
print("enabled sound setting")
case .disabled:
print("setting has been disabled")
case .notSupported:
print("something vital went wrong here")
}
}
application.registerForRemoteNotifications()
} else {
let settings = UIUserNotificationSettings(types: [.alert, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
I hope it will help you out!
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.