Is there any different to install UNUserNotificationCenterDelegate in willFinishLaunchingWithOptions or didFinishLaunchingWithOptions? - ios

Currently, this is my code-snippet, in handling tap action, of local notification.
The following code will launch a UIViewController, when user taps on the local notification.
import UIKit
extension UIApplication {
//
// https://stackoverflow.com/a/58031897/72437
//
var keyWindow: UIWindow? {
// Get connected scenes
UIApplication
.shared
.connectedScenes
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first { $0.isKeyWindow }
}
}
#main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
// This method is called when user clicked on the notification
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void)
{
let newViewController = NewViewController.instanceFromNib()
newViewController.postInit(response.notification.request.identifier)
UIApplication.shared.keyWindow?.rootViewController?.present(newViewController, animated: false, completion: nil)
completionHandler()
}
}
What I am puzzling is, should I install UNUserNotificationCenterDelegate during willFinishLaunchingWithOptions, or didFinishLaunchingWithOptions?
Install during willFinishLaunchingWithOptions
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
Install during didFinishLaunchingWithOptions
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
Based on https://developer.apple.com/documentation/usernotifications/unusernotificationcenterdelegate
You must assign your delegate object to the UNUserNotificationCenter
object before your app finishes launching. For example, in an iOS app,
you must assign it in the
application(:willFinishLaunchingWithOptions:) or
application(:didFinishLaunchingWithOptions:) method of your app
delegate. Assigning a delegate after the system calls these methods
might cause you to miss incoming notifications.
It seems like there is no difference between willFinishLaunchingWithOptions and didFinishLaunchingWithOptions
I was wondering, do you find any differences, between willFinishLaunchingWithOptions and didFinishLaunchingWithOptions, as far as UNUserNotificationCenterDelegate installation is concerned?
Thanks.

Related

No windows have a root view controller, cannot save application state

When ever I try to open the application by clicking the notification this No windows have a root view controller, cannot save application state error is showing and it's not navigating to the correct page. the app just opens that all.
How should I solve this ?
AppleDelegate:
import UIKit
import Flutter
import Firebase
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate
}
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, shouldSaveSecureApplicationState coder: NSCoder) -> Bool {
return true
}
override func application(_ application: UIApplication, shouldRestoreSecureApplicationState coder: NSCoder) -> Bool {
return true
}
override func applicationDidBecomeActive(_ application: UIApplication) {
signal(SIGPIPE, SIG_IGN);
}
override func applicationWillEnterForeground(_ application: UIApplication) {
signal(SIGPIPE, SIG_IGN);
}
override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
return super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
}
}

Flutter/Ios - Firebase Phone auth using with FCM App crashes on real device only for first time

Everything works fine after the second time. this issue only occurs once per device, making it hard to debug.
Even if I restarted the device issue doesn't appear again but as it always happens for new users the first time.
AppDelegate.Swift
import UIKit
import Flutter
import flutter_downloader
import Firebase
#UIApplicationMain
#objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
FlutterDownloaderPlugin.setPluginRegistrantCallback(registerPlugins)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
if(!UserDefaults.standard.bool(forKey: "Notification")) {
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
UserDefaults.standard.set(true, forKey: "Notification")
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
override func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
super.application(application, didReceiveRemoteNotification: userInfo, fetchCompletionHandler: completionHandler)
let firebaseAuth = Auth.auth()
Messaging.messaging().appDidReceiveMessage(userInfo)
print(userInfo)
if (firebaseAuth.canHandleNotification(userInfo)){
completionHandler(.noData)
return
}
}
}
private func registerPlugins(registry: FlutterPluginRegistry) {
if (!registry.hasPlugin("FlutterDownloaderPlugin")) {
FlutterDownloaderPlugin.register(with: registry.registrar(forPlugin: "FlutterDownloaderPlugin")!)
}
}
Crash Log:
specialized AppDelegate.application(_:didReceiveRemoteNotification:fetchCompletionHandler:) + 600 (AppDelegate.swift:29)

Is it safe to put Realm.Configuration into shouldRestoreApplicationState?

I'm implementing the app restoration features.
But I found that viewDidLoad is called before didFinishLaunchingWithOptions gets called.
And I have to read some data from database here.
So it always throws exception on try! Realm().
Anyway, here's how I do it for now.
var realmConfigured = false
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
configureRealm()
}
func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
print("restoring")
configureRealm()
return true
}
func configureRealm(){
guard !realmConfigured else { return }
realmConfigured = true
let config = Realm.Configuration(...)
Realm.Configuration.defaultConfiguration = config
}
And it works fine so far.
Is there a better way to do this?

Appdelegate print() not working

I want to open my iOS app from and URL but when I put NSURL into fund application print() doesn't working.
please refer here
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var openUrl:NSURL? //This is used when to save state when App is not running before the url trigered
func application(_ application: UIApplication, openURL url: NSURL, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//print("Host: \(url.host!)")
//let url = url.standardized
//NotificationCenter.default.post(name: NSNotification.Name(rawValue: "HANDLEOPENURL"), object:url!)
print("bbb")
return true
}
}
There is no AppDelegate method with that signature, so its not getting called
func application(_ application: UIApplication, openURL url: NSURL, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
The correct method signature is:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool`
You are confusing it with this method
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
EDIT
To respond to links from the web to iOS, use
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {

iOS push notification via Firebase not working

Hello I'm making an iPhone app where I send push notifications via Google's Firebase. I'm using Swift and Xcode for the programming. When I open the app I get asked to allow push notifications, however I don't receive any when I send them from the Firebase Console. I was wondering if you could help me out. I'm using Ad Hoc export to transfer an .isa to my friend's iPhone and test it that way. I followed exactly the Firebase tutorial - adding the .plist, the cocoa pod and I uploaded a certificate in the project settings. I have a paid apple developer account.
import UIKit
import CoreData
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FIRApp.configure()
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.Alert,UIUserNotificationType.Badge,UIUserNotificationType.Sound]
let notificationSettings = UIUserNotificationSettings(forTypes:notificationTypes, categories:nil)
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(notificationSettings)
return true
}
func applicationWillResignActive(application: UIApplication) {
}
func applicationDidEnterBackground(application: UIApplication) {
}
func applicationWillEnterForeground(application: UIApplication) {
}
func applicationDidBecomeActive(application: UIApplication) {
}
func applicationWillTerminate(application: UIApplication) {
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("MessageID : \(userInfo["gcm_message_id"]!)")
print("%#", userInfo)
}
}
There are a few more things you need to do. When you registerForRemoteNotifications, you receive an APNS Token which you need to give to Firebase. This is done in application didRegisterForRemoteNotificationsWithDeviceToken.
import UIKit
import CoreData
import Firebase
import FirebaseMessaging
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
override init() {
super.init()
FIRApp.configure()
}
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.registerForRemoteNotifications()
application.registerUserNotificationSettings(
UIUserNotificationSettings(
forTypes: [.Alert, .Badge, .Sound],
categories: nil
)
)
NSNotificationCenter.defaultCenter().addObserver(self,
selector: #selector(tokenRefreshNotification),
name: kFIRInstanceIDTokenRefreshNotification,
object: nil
)
return true
}
func applicationDidEnterBackground(application: UIApplication) {
FIRMessaging.messaging().disconnect()
}
func applicationDidBecomeActive(application: UIApplication) {
FIRMessaging.messaging().connectWithCompletion { (error) in
switch error {
case .Some:
print("Unable to connect with FCM. \(error)")
case .None:
print("Connected to FCM.")
}
}
}
func applicationWillResignActive(application: UIApplication) {}
func applicationWillEnterForeground(application: UIApplication) {}
func applicationWillTerminate(application: UIApplication) {}
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
FIRInstanceID.instanceID().setAPNSToken(deviceToken, type: .Sandbox)
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
print("MessageID : \(userInfo["gcm.message_id"]!)")
print("%#", userInfo)
}
func tokenRefreshNotification(notification: NSNotification) {
if let refreshedToken = FIRInstanceID.instanceID().token() {
print("Instance ID token: \(refreshedToken)")
}
applicationDidBecomeActive(UIApplication.sharedApplication())
}
}

Resources