10

I am trying to send the user a 'Push Notification style' Alert when the user minimizes the app (by clicking on the iPhone's Home Button or by locking the phone as well).

My app continuously parses an XML file (every 10 seconds) and I want the app to continue running so that it sends the user a Local Notification once some condition has been met in my program, even after the user has minimized the app or locked their phone.

I've bounced around from tutorials and everyone seems to 'schedule' a Notification, but this isn't going to work for me because my Notification isn't time-based, rather it's based off conditions being met.

What I've done so far:

AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil))
    return true
}

MapViewController.swift

// Some function
func someFunction(delta: Int) {
    if delta < 100 {
        // Send alert to user if app is open
        let alertView = UIAlertController(title: "This is an Alert!", message: "", preferredStyle: UIAlertControllerStyle.Alert)
        alertView.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
        self.presentViewController(alertView, animated: true, completion: nil)

        // Send user a local notification if they have the app running in the bg
        pushTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("pushNotification"), userInfo: nil, repeats: false)
    }
}

// Send user a local notification if they have the app running in the bg
func pushNotification() {
    let notification = UILocalNotification()
    notification.alertAction = "Go back to App"
    notification.alertBody = "This is a Notification!"
    notification.fireDate = NSDate(timeIntervalSinceNow: 1)
    UIApplication.sharedApplication().scheduleLocalNotification(notification)
}

The Alert works great while the app is open, but the notification never shows up when I minimize the app on my phone. I assume the app isn't running while it's in the background or I don't understand this concept that well. Any help is greatly appreciated.

Ivan
  • 480
  • 2
  • 9
  • 24
  • What is this delta? I guess your function is not called in background and hence your notification dint get scheduled – Muneeba Jan 26 '16 at 07:38
  • @Muneeba delta is inside 'someFunction' I just didn't include the entire code (trying to keep relevant pieces). I've edited the code so that it is a bit more readable. The stuff inside the 'if' statement is being executed, I've verified with 'print()' statements. – Ivan Jan 26 '16 at 07:43
  • Write print statement in pushNotification function and see if it gets called in bg. – Muneeba Jan 26 '16 at 07:47
  • @Muneeba Ok, pushNotification() is getting called and works when I minimize my app in the simulator, but when I upload the app to my phone and minimize the app, I don't get the alerts like I do in the simulator. – Ivan Jan 26 '16 at 07:52
  • Did you get the permission popup? – Muneeba Jan 26 '16 at 09:17
  • @Muneeba Yes, the app asks the user to 'Allow Push Notifications' and I've set them to 'Yes' and my device is not on 'Do Not Disturb'. [This](http://stackoverflow.com/questions/28050984/local-notifications-are-not-working-on-device-but-working-on-simulator) explains that on an iOS device, when the app is in the background, it is not actually running (gets no CPU time) and the task gets suspended. So, I'm assuming there's a way to keep the app running in the bg on the device while the app is minimized or device locked, just don't know how. – Ivan Jan 26 '16 at 18:44

1 Answers1

13

By default NSTimer does work only in simulator. Try to add this to your AppDelegate file:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil))

application.beginBackgroundTaskWithName("showNotification", expirationHandler: nil)

        return true
    }
nadi9
  • 566
  • 3
  • 11
  • Yes! That worked! Thank you! Is there a reason why a Sound doesn't play when the notification gets fired? I'm setting the notification type to [.Sound, .Alert, .Badge] so a Sound should play. Unless I have to set it up elsewhere as well. – Ivan Jan 27 '16 at 06:08
  • 1
    Never mind. I got it working by adding **notification.soundName = UILocalNotificationDefaultSoundName** in my pushNotification() function. Thank you for your help! – Ivan Jan 27 '16 at 06:25
  • 1
    Did you add this to your notification? notification.soundName = UILocalNotificationDefaultSoundName – nadi9 Jan 27 '16 at 06:28
  • Yes I did, the notification sound is working now. Thank you. – Ivan Jan 27 '16 at 06:36
  • 2
    @Nadia After countless hours of searching and tutorials, the "beingbackgroundtaskwithname" worked. Thank you for this answer – Cognoscis Mar 24 '17 at 12:44