So what i am trying to achieve is when a notification launch and the user tap on it, an Alert controller should appear with 2 options. However, when the app launch from the notification tap, nothing appears.
These codes are inside the AppDelegate.swift file
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
showAlert()
}
func showAlert() {
let alert = UIAlertController(title: "Confirm", message: "Confirm?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "No", style: .destructive, handler: nil))
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: nil))
window?.rootViewController?.present(alert, animated: true, completion: nil)
}
var topVC: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
topVC?.rootViewController = UIViewController()
let alert = UIAlertController(title: "Alert", message: "Notification Received", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel) { _ in
// action OK
})
topVC?.makeKeyAndVisible()
topVC?.rootViewController?.present(alert, animated: true, completion: nil)
Try this:
func showAlert() {
var alertController = UIAlertController(title: "Confirm", message: "Confirm?", preferredStyle: UIAlertControllerStyle.alert)
var okAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) {
UIAlertAction in
// action
}
var cancelAction = UIAlertAction(title: "No", style: UIAlertActionStyle.Cancel) {
UIAlertAction in
// action
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
}
I think you are calling the func showAlert() from the wrong place.
When the app launch from the notification tap, the app gets an event in
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
So you should try this,
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//Handle remote notification event on app launch
if let remoteNotification = launchOptions?[UIApplication.LaunchOptionsKey.remoteNotification] {
showAlert()
}
}
Related
In context of this question/answer I've attempted but the result is no alert presented.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let alertController = UIAlertController(title: "Error", message: "ABc", preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
let win = UIWindow(frame: UIScreen.main.bounds)
let vc = UIViewController()
vc.view.backgroundColor = .clear
win.rootViewController = vc
win.windowLevel = UIWindow.Level.alert + 1 // Swift 3-4: UIWindowLevelAlert + 1
win.makeKeyAndVisible()
vc.present(alertController, animated: true, completion: nil)
return true
}
Attempt 2 based on the answer.
Use below line:
self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
Instead of
vc.present(alertController, animated: true, completion: nil)
than problem is solved.
Example:
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5, execute: {
let alertController = UIAlertController(title: "Alert Title", message:
"Message", preferredStyle: .actionSheet)
let okAction = UIAlertAction(title: "Ok", style:.default) {
UIAlertAction in
NSLog("OK Pressed")
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) {
UIAlertAction in
NSLog("Cancel Pressed")
}
alertController.addAction(okAction)
alertController.addAction(cancelAction)
self.window?.rootViewController?.present(alertController, animated: true, completion: nil)
})
I display a UIAlertController from the AppDelegate when a push notification is received and the app is open. The problem is, the alert does not show the first time the app is run. If you stop the app in Xcode and then re-start it, everything works as expected.
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
var alert: UIAlertController?
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (_ options: UNNotificationPresentationOptions) -> Void) {
self.showAlert(title: title,message:body,buttonTitle:"View",window:self.window!)
}
func showAlert(title: String,message : String,buttonTitle: String,window: UIWindow){
self.alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.alert)
alert?.addAction(UIAlertAction(title: buttonTitle, style: UIAlertActionStyle.default, handler: { (action) in
//self.messageDelegate?.goToMessages()
}))
alert?.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default, handler: nil))
window.rootViewController?.present(alert!, animated: false, completion: nil)
}
}
I want to show alertViewController on my rootViewController in AppDelegate when app is launched. Here snippet of code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let alert: UIAlertController = UIAlertController(title: "This is title", message: "This is message.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default))
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
return true
}
alert is not appearing on rootViewController. Please help me.
The reason is that the view isn't yet loaded, if you look at console you may find log like this:
Warning: Attempt to present on 'swiftHere.ViewController: 0x7ff289007740' whose view is not in the window hierarchy!
You may dispatch it until rootViewController loads:
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let alert: UIAlertController = UIAlertController(title: "This is title", message: "This is message.", preferredStyle: UIAlertControllerStyle.alert)
alert.addAction(UIAlertAction(title: "Ok", style: .default))
self.window?.rootViewController?.present(alert, animated: true, completion: nil)
}
everyone!
When my app in foreground I want it to show alert when DidReceiveLocalNotification triggered.
I can add alert to mimic local notifications in AppDelegate.swift, but the problem is I don't know how to add method from my ViewController to UIAlertAction closure (see commented line), to finish animation when timer stopped.
My code below:
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
let alertTimerEnds = UIAlertController(title: "Timer finished!", message: nil, preferredStyle: .Alert)
let okAction = UIAlertAction(title: "OK", style: .Default) { finished in
print("You've pressed OK button")
//self.ViewController().finishAnimation()
}
alertTimerEnds.addAction(okAction)
self.window?.rootViewController?.presentViewController(alertTimerEnds, animated: true, completion: nil)
}
Maybe I should do it in ViewController usind AppDelegate?
let someAppDelegate = UIApplication.sharedApplication().delegate as? AppDelegate
someAppDelegate?.application(UIApplication.sharedApplication(), didReceiveLocalNotification: UILocalNotification) { code for alert }
If you want to do that
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification)
{
var viewController : UIViewController = (application.keyWindow?.rootViewController)!
while ((viewController.presentedViewController) != nil) {
viewController = viewController.presentedViewController!
}
let alert = UIAlertController(title: "", message: notification.alertBody, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: {(action: UIAlertAction!) in}))
viewController.presentViewController(alert, animated: true, completion: nil)
})
Show UIAlertController in didReceiveLocalNotification method
Try with below code, this will display alert on viewcontroller which is present at a moment.
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
var latestViewController : UIViewController!
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if let viewControllers = appDelegate.window?.rootViewController?.presentedViewController {
latestViewController = viewControllers as UIViewController
}
else if let viewControllers = appDelegate.window?.rootViewController?.childViewControllers {
latestViewController = viewControllers.last! as UIViewController
}
//var alert: UIAlertView!
//alert = UIAlertView(title: "Title", message:"Message , delegate: nil, cancelButtonTitle:"Ok" )
//alert.show()
let alert = UIAlertController(title: "Title", message:"Message", preferredStyle: .Alert)
let action = UIAlertAction(title: "OK", style: .Default) { _ in
// Put here any code that you would like to execute when
// the user taps that OK button (may be empty in your case if that's just
// an informative alert)
}
alert.addAction(action)
latestViewController.presentViewController(alert, animated: true){}
}
How do I migrate from UIAlertView (deprecated in iOS8)
I'm adding remote notifications with ArenaDeamons, but I'm getting an error (MY APP KEY is my private key):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
BDArenaConnector.initializeWithAppKey("MY APP KEY", runInSandboxEnvironment: true)
BDArenaConnector.getInstance().requestAuth()
// register for remote notifications
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings.settingsForTypes((UIUserNotificationTypeSound|UIUserNotificationTypeAlert|UIUserNotificationTypeBadge), categories: nil))
UIApplication.sharedApplication().registerForRemoteNotifications()
BDArenaConnector.getInstance().pushConnector.feedbackServiceDidFinishLaunchingWithOptions(launchOptions)
return true
UINavigationBar.appearance().barTintColor = UIColor.redColor()
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
UIBarButtonItem.appearance().tintColor = UIColor.blueColor()
UINavigationBar.appearance().tintColor = UIColor.whiteColor()
return true
}
Error1: use of unresolved identifier 'UIUserNotificationTypeBadge'
Error2: use of unresolved identifier 'UIUserNotificationTypeSound'
Error3: use of unresolved identifier 'UIUserNotificationTypeAlert'
I also have some errors here:
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("UIApplication : didFailToRegisterForRemoteNotificationsWithError : \(error.localizedDescription)")
var alert: UIAlertController = UIAlertController(title: "did Fail To Register For Remote Notifications", message: error.localizedDescription(), preferredStyle: UIAlertControllerStyleAlert)
var okAction: UIAlertAction = UIAlertAction.actionWithTitle("Ok!", style: UIAlertActionStyleDefault, handler: { (action: UIAlertAction) in
})
alert.addAction(okAction)
self.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)
}
Error1: use of unresolved identifier 'UIalertcontrollerstylealert'
Error2: use of unresolved identifier 'UIalertactionstyledefault'
How Can I fix it? The app is in Swift 2.
For ios 8 and above, you can use registerUserNotificationSettings,
try this code, i have not tested it but, it will help you for sure.
let types = UIUserNotificationType.Badge.union(UIUserNotificationType.Alert).union(UIUserNotificationType.Sound)
UIApplication.sharedApplication().registerUserNotificationSettings(UIUserNotificationSettings(forTypes: types, categories: nil))
UIApplication.sharedApplication().registerForRemoteNotifications()
Fix for Error 3
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("UIApplication : didFailToRegisterForRemoteNotificationsWithError : \(error.localizedDescription)")
let alert: UIAlertController = UIAlertController(title: "did Fail To Register For Remote Notifications", message: error.localizedDescription, preferredStyle: UIAlertControllerStyle.Alert)
let okAction: UIAlertAction = UIAlertAction(title: "Ok!", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction) in
})
alert.addAction(okAction)
self.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)
}
Fixed in part. Now I have only 2 errors. Thanks Prabhu.Somasundaram.
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
print("UIApplication : didFailToRegisterForRemoteNotificationsWithError : \(error.localizedDescription)")
let alert: UIAlertController = UIAlertController(title: "did Fail To Register For Remote Notifications", message: error.localizedDescription, preferredStyle: UIAlertControllerStyle.Alert)
let okAction: UIAlertAction = UIAlertAction(title: "Ok!", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction) in
})
alert.addAction(okAction)
self.window!.rootViewController!.presentViewController(alert, animated: true, completion: nil)
}
Error 1: invalid use of '()' to call a value of non-function Type 'String'
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
BDArenaConnector.getInstance().pushConnector.feedbackServiceDidReceiveRemoteNotification(userInfo)
// handle push
BDArenaConnector.getInstance().pushConnector.handlePush(userInfo, withPresentingController: self.window!.rootViewController, withActionButtonHandler: {
}, withCancelButtonHandler: {
})
}
Error 2: Value of optional type 'UIWindow' not unwrapped; did you mean to use '!' or '?'?
How Can I fix?
You need to use UIAlertActionStyle.Default and UIAlertControllerStyle.Alert.