Geofencing UILocalNotification not working properly swift - ios

I am facing a strange problem with local notification in swift.
I am presenting local notification like this
let notification = UILocalNotification()
var body = "Hi Krishna";
if(region.identifier == "entry1") {
body += " Welcome";
} else {
body += " Bye! Bye!";
}
notification.alertBody = body
notification.soundName = "Default";
notification.userInfo = ["id": "id"];
notification.fireDate = NSDate(timeIntervalSinceNow: 1)
UIApplication.sharedApplication().scheduleLocalNotification(notification)
and how I am handling launch options in my appdelegate
if(launchOptions != nil) {
window?.rootViewController?.view.backgroundColor = UIColor.cyanColor();
if let notification = launchOptions![UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
window?.rootViewController?.view.backgroundColor = UIColor.blackColor();
if let userInfo = notification.userInfo {
window?.rootViewController?.view.backgroundColor = UIColor.blueColor();
if let id = userInfo["id"] as? String {
window?.rootViewController?.view.backgroundColor = UIColor.redColor();
}
}
}
}
for debugging purpose I am changing the background color of the view.
when I tap to the notification I get the cyan color that means below line is failing
launchOptions![UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification
because I set cyan color right above this line.
so I am not getting why this is not castable to UILocalNotification?
can somebody help me to get rid from this issue?+
one more thing actually if I am doing it normally its working but I am using geofencing and I am scheduling notification from
locationManager(manager: CLLocationManager, didExitRegion region: CLRegion)
In this case its not working.

You could implement application(_:didReceiveLocalNotification:) (which gives you the notification directly) in your AppDelegate and handle the notification there.
More: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:didReceiveLocalNotification:

Can you please try to cast like this:
if let notification:UILocalNotification = launchOptions?[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
//do stuff with notification
}

Related

How to cancel or delete on my lock screen after seen UILocalNotification in swift3?

How to solve this problem? Please help me.
I used the following code in my project, but can't delete notification.
if #available(iOS 10.0, 😉 {
let center = UNUserNotificationCenter.current()
center.removeDeliveredNotifications(withIdentifiers: [String(self.chatRoom.getChatRoomID())])
} else {
// Fallback on earlier versions
}
var app:UIApplication = UIApplication.shared
for oneEvent in app.scheduledLocalNotifications! {
var notification = oneEvent as UILocalNotification
let userInfoCurrent = notification.userInfo! as! [String:AnyObject]
let uid = userInfoCurrent["TeamChatRoomID"]! as! String
if uid == String(self.chatRoom.getChatRoomID()){
//Cancelling local notification
app.cancelLocalNotification(notification)
break;
}
}
To clear all the notification from notification center
ios>10:
https://developer.apple.com/documentation/usernotifications/unusernotificationcenter
ios<10:
setting application badge number to 0 should do the trick
But I am not sure if this is what you are looking for, as the question is unclear.

How to conditionally push local notification in ios app?

i'm working on an ios app which will send notification after the app being sent to the background. I only want the notification to work when the user set a value to true in MainviewController.swift. So I have something like this :
func setDelegateToTrue () {
Appdelegate().setToStart()
}
func setDelegateToFalse () {
Appdelegate().setToEnd()
}
and in my Appdelegate.swift, I have something like this :
var started = false
func applicationDidEnterBackground(application: UIApplication) {
if(started) {
let notification: UILocalNotification = UILocalNotification()
notification.category = "FIRST_CATEGORY"
notification.alertBody = "do not forget your app"
notification.repeatInterval = NSCalendarUnit.Day
notification.timeZone = NSTimeZone.defaultTimeZone()
UIApplication.sharedApplication().scheduleLocalNotification(notification)
started = false
}
}
func setToStart() {
started = true
}
func setToEnd() {
started = false
}
The notification works fine while there is no if statement, however, when I have the if statement and call setDelegateToTrue() in viewdidload, it stopped working. It seems like the boolean value started was to changed after calling setToStart(), but I actually can print things out of setToStart(). Can anyone help me?
Your problem is that you're creating a new instance of AppDelegate when you run AppDelegate().setToStart(). So, when the application delegate it called later it's flag is still set to false, because you set a flag on a different instance (which was immediately destroyed).
To do what you're currently trying to you need to get the delegate from UIApplication (the sharedApplication) and set the flag on that.
Bear this in mind when communication with view controllers and such in OO languages as you always need to get the instance you want to talk to rather than create a new one.
For this behaviour you can make use of NSUserDefault:
Set the value inside the Main ViewController as:
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "shouldSendNotification")
And access this user default in applicationDidEnterBackground of app delegate as follow:
func applicationDidEnterBackground(application: UIApplication) {
let shouldSendNotification = NSUserDefaults.standardUserDefaults().boolForKey("shouldSendNotification")
if shouldSendNotification {
let notification: UILocalNotification = UILocalNotification()
notification.category = "FIRST_CATEGORY"
notification.alertBody = "do not forget your app"
notification.repeatInterval = NSCalendarUnit.Day
notification.timeZone = NSTimeZone.defaultTimeZone()
UIApplication.sharedApplication().scheduleLocalNotification(notification)
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "shouldSendNotification")
}
}
You need to do is
func setDelegateToTrue () {
AppDelegate.sharedAppDelegate().setToStart()
}
func setDelegateToFalse () {
AppDelegate.sharedAppDelegate().setToEnd()
}

Push notification displaying whole receiving content when is on background

I'm developing a chat app. I'm using apple push notification service to notify user when he receives new messages. There are two scenarios.
The first when user is chatting and receiving a message, the user shouldn't be notified (meaning that notification shouldn't be shown) and when the app is in background i want to alert user for the messages. Everything is ok except that when app is on background the notification shows the whole JSON object the client is receiving.
The idea is ignore visually notification and if its on background show a local Notification.
This is how i have implemented the notification settings
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let types: UIUserNotificationType = [UIUserNotificationType.None]
let settings: UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
return true
}
func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject])
{
//App handle notifications in background state
if application.applicationState == UIApplicationState.Background {
var login_user = LoginUser();
login_user.loadData();
var username:String!;
var message:String!;
if let msg = userInfo["aps"]as? Dictionary<String,AnyObject>
{
if let alert = msg["alert"] as? String{
if let data = alert.dataUsingEncoding(NSUTF8StringEncoding)
{
do
{
let jsonObject = try NSJSONSerialization.JSONObjectWithData(data,options: [])
username = jsonObject["senderUserName"] as! String;
message = jsonObject["content"] as! String!;
DatabaseOperations().insert(DatabaseOperations().STRING_VALUE_CHATING_USERNAME, value: username);
NSNotificationCenter.defaultCenter().postNotificationName("push_notification", object: self)
}
catch
{
}
}
}
}
let localNotification: UILocalNotification = UILocalNotification()
switch(login_user.privacyLevelId)
{
case 1:
localNotification.alertBody = username + ":" + message;
break;
case 2:
localNotification.alertBody = username;
break;
case 3:
localNotification.alertBody = "New Message";
break;
default:
localNotification.alertBody = "New Message";
break;
}
localNotification.alertAction = "Message"
localNotification.fireDate = NSDate(timeIntervalSinceNow: 5)
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
}
//App is shown and active
else
{
if let msg = userInfo["aps"]as? Dictionary<String,AnyObject>
{
if let alert = msg["alert"] as? String
{
if let data = alert.dataUsingEncoding(NSUTF8StringEncoding)
{
do
{
let jsonObject = try NSJSONSerialization.JSONObjectWithData(data,options: [])
let sender:String = jsonObject["senderUserName"] as! String;
DatabaseOperations().insert(DatabaseOperations().STRING_VALUE_CHATING_USERNAME, value: sender);
NSNotificationCenter.defaultCenter().postNotificationName("push_notification", object: self)
}
catch
{
}
}
}
}
}
}
I set UIUserNotificationType to NONE. Shouldn't by default the notification shows nothing?
I also have read some other posts, but i couldn't find anything to solve the problem.
Why does UIUserNotificationType.None return true in the current settings when user permission is given?
Hide, do not display remote notification from code (swift)
Any help would be appreciated.
application didReceiveRemoteNotification won't be called if the app is closed or in the background state, so you won't be able to create a local notification. So you need to pass the text you want to display in the aps dictionnary, associated with the alert key.
If you want to pass more information for the active state case, you should add them with a custom key to the push dictionnary.
For example :
{"aps": {
"badge": 1,
"alert": "Hello World!",
"sound": "sound.caf"},
"task_id": 1}

how to cancel a localNotification with the press of a button in swift?

I am scheduling a location based UILocalNotification with the click of a button . But when i try to cancel the localNotification by clicking the same button again, it doesn't cancel the notification.
I am using UIApplication.sharedApplication().cancelLocalNotification(localNotification)
to cancel my scheduled location based local notification.
What am i doing wrong ?
here is my implementation
#IBAction func setNotification(sender: UIButton!) {
if sender.tag == 999 {
sender.setImage(UIImage(named: "NotificationFilled")!, forState: .Normal)
sender.tag = 0
regionMonitor() //function where notification get scheduled
} else {
sender.setImage(UIImage(named: "Notification")!, forState: .Normal)
sender.tag = 999 }
what should i enter into the else block so that the scheduled notification gets canceled. Cannot clear all notifications.
here is the didEnterRegion block code where i trigger the local notification
func locationManager(manager: CLLocationManager!, didEnterRegion region: CLRegion!) {
localNotification.regionTriggersOnce = true
localNotification.alertBody = "Stack Overflow is great"
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
NSLog("Entering region")
}
You could try to remove all notifications if this is acceptable in your context.
Like this:
for notification in UIApplication.sharedApplication().scheduledLocalNotifications as! [UILocalNotification] {
UIApplication.sharedApplication().cancelLocalNotification(notification)
}
Or as stated by Logan:
UIApplication.sharedApplication().cancelAllLocalNotifications()
Or as stated by Gerard Grundy for Swift 4:
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
You can cancel a notification using its identifier :
let center = UNUserNotificationCenter.current()
center.removeDeliveredNotifications(withIdentifiers: [String])
center.removePendingNotificationRequests(withIdentifiers: [String])
Solution for iOS 10+ Swift 3.1
let center = UNUserNotificationCenter.current()
center.removeAllDeliveredNotifications() // To remove all delivered notifications
center.removeAllPendingNotificationRequests()
You can save a unique value for key in your local notification's userinfo and cancel it by getting the localnotification using that key's Value.
Try this (for Objective C):
NSArray *notifArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
for (int i=0; i<[notifArray count]; i++)
{
UILocalNotification* notif = [notifArray objectAtIndex:i];
NSDictionary *userInfoDict = notif.userInfo;
NSString *uniqueKeyVal=[NSString stringWithFormat:#"%#",[userInfoDict valueForKey:#"UniqueKey"]];
if ([uniqueKeyVal isEqualToString:keyValToDelete])
{
[[UIApplication sharedApplication] cancelLocalNotification:notif];
break;
}
}
For Swift 3.0 and iOS 10:
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
Hard to tell without seeing the implementation of the code.
so you have an
- IBAction methodName{
//scheduleNotification
//cancelNotification
}
Is that about right? If so add a bool so
Bool didCancel;
- IBAction methodName{
if didCancel == No{
//scheduleNotification
didCancel = YES;
}else if didCancel == YES{
//cancelNotifications
didCancel = NO;
}

iOS locale notification pop-up doesn't appear

I'm a newbie in iOS programming and in my app I've a UILocaleNotification which have to appear at a certain time.
So first I setup parameters :
let notificationSettings: UIUserNotificationSettings! = UIApplication.sharedApplication().currentUserNotificationSettings()
if (notificationSettings.types == UIUserNotificationType.None) {
var notificationTypes: UIUserNotificationType = UIUserNotificationType.Alert | UIUserNotificationType.Sound
// Bouton d'envoi
var sendAction = UIMutableUserNotificationAction()
sendAction.identifier = "send"
sendAction.title = "Send"
sendAction.activationMode = UIUserNotificationActivationMode.Foreground
sendAction.destructive = false
sendAction.authenticationRequired = true
// Bouton de non-envoi
var dontSendAction = UIMutableUserNotificationAction()
dontSendAction.identifier = "dontsend"
dontSendAction.title = "Don't send"
dontSendAction.activationMode = UIUserNotificationActivationMode.Background
dontSendAction.destructive = true
dontSendAction.authenticationRequired = false
let actionsArray = NSArray(objects: sendAction, dontSendAction)
var reminderNotification = UIMutableUserNotificationCategory()
reminderNotification.identifier = "reminderNotification"
reminderNotification.setActions(actionsArray as [AnyObject], forContext: UIUserNotificationActionContext.Minimal)
let categoriesForSettings = NSSet(objects: reminderNotification)
let newNotificationSettings = UIUserNotificationSettings(forTypes: notificationTypes, categories: categoriesForSettings as Set<NSObject>)
UIApplication.sharedApplication().registerUserNotificationSettings(newNotificationSettings)
}
... and I schedule my notification like that :
var localNotification = UILocalNotification()
localNotification.fireDate = NSDate(timeIntervalSinceNow: 3)
localNotification.timeZone = NSTimeZone.defaultTimeZone()
localNotification.alertBody = "Hey, inform your contacts !"
localNotification.alertAction = "Send Message"
localNotification.category = "reminderNotification"
localNotification.soundName = UILocalNotificationDefaultSoundName
UIApplication.sharedApplication().scheduleLocalNotification(localNotification)
When I try this code, notifs are displaying right in the notification center, but there is no pop-up displayed...
I searched sources on the net and I don't understand why those examples and tutos are displaying pop-up because I wrote the same code...
Thanks for your help and have a good day !
EDIT : I forgot something : it's the notification center which have to detect an event, and not the locale notification. So I want the addObserver of the notification center to check an event, is it possible in background state ?
According to this line: localNotification.fireDate = NSDate(timeIntervalSinceNow: 3) you want your notification to be triggered 3 seconds later. I assume that the app is still in the foreground when it happens. If it's the case, you will not have a notification popup.
If the app linked to a notification is opened when the notification is received, it has to handle it in your AppDelegate to display a custom popup.
func application(application: UIApplication!, didReceiveLocalNotification notification: UILocalNotification!) {
// do your jobs here
}

Resources