4

I am coding in Swift 3 and I am simply trying to send a notification now without any delays or intervals. However the notification never gets triggered. Here's my code..

The ViewController code

import UserNotifications

class HomeViewController: UIViewController{
    var isGrantedNotificationAccess:Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        UNUserNotificationCenter.current().requestAuthorization(
            options: [.alert,.sound,.badge],
            completionHandler: { (granted,error) in
                self.isGrantedNotificationAccess = granted
        })

        if isGrantedNotificationAccess{
            triggerNotification()
        }
    }

    //triggerNotification func goes here
}

triggerNotification function:

func triggerNotification(){
    let content = UNMutableNotificationContent()
    content.title = NSString.localizedUserNotificationString(forKey: "Notification Testing", arguments: nil)
    content.body = NSString.localizedUserNotificationString(forKey: "This is a test", arguments: nil)
    content.sound = UNNotificationSound.default()
    content.badge = (UIApplication.shared.applicationIconBadgeNumber + 1) as NSNumber;
    let trigger = UNTimeIntervalNotificationTrigger(
        timeInterval: 1.0,
        repeats: false)

    let request = UNNotificationRequest.init(identifier: "testTriggerNotif", content: content, trigger: trigger)

    let center = UNUserNotificationCenter.current()
    center.add(request)
}

What am I doing wrong?

pkamb
  • 33,281
  • 23
  • 160
  • 191
Jay
  • 4,873
  • 7
  • 72
  • 137
  • You can refer this link - http://stackoverflow.com/questions/37807302/add-local-notification-in-ios10-swift-3 – Nilesh Dec 29 '16 at 05:29
  • Your notifications are working fine. For testing increase time interval to 5 and move app in background.(Notification banner will appear as expected. The issue is that you are not dealing the case what should app do then the user notification arrives and app is in foreground state) – Muhammad Adnan Dec 29 '16 at 05:48

2 Answers2

9

You were missing the handling, when the app is in foreground, you were not specifying how the notifications would look like or be presented.

Set below line while adding notification to specify that you want to show banner while user is using app (iOS 10 new feature).

Add the following line of code when constructing your UNMutableNotificationContent object:

content.setValue("YES", forKeyPath: "shouldAlwaysAlertWhileAppIsForeground")

You should also add the following method in your AppDelegate:

// This method will be called when app received push notifications in foreground

func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler(UNNotificationPresentationOptions.alert)        
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Muhammad Adnan
  • 2,668
  • 15
  • 27
  • Where do I add this? Inside the viewDidLoad? – Jay Dec 29 '16 at 05:52
  • @RickGrimesLikesWalkerSoup use updated answer. Just add the key and method below in Appdelegate. – Muhammad Adnan Dec 29 '16 at 06:25
  • @RickGrimeslikesWalkerSoup Its preferable to get permission from user in appdelegate method . And also create trigger notification method in appdelegate so that it can be used anywhere later. – Muhammad Adnan Dec 29 '16 at 06:49
  • Noted and I did that as well – Jay Dec 29 '16 at 07:24
  • 2
    Th setValue(forKey:) method is a completely undocumented key and not guaranteed to work in the future (or at all). It's not necessary either. The UNUserNotificationCenter delegate approach is all you need, and is documented. You have to specifically implement `UNUserNotificationCenterDelegate` in your app delegate and set `UNUserNotificationCenter`'s delegate to the app delegate in `didFinishLaunchingWithOptions` to make this work. – Bill Aug 18 '17 at 12:48
  • 11
    `shouldAlwaysAlertWhileAppIsForeground` is no longer supported in iOS 12 and the code crashes. – Ortwin Gentz Aug 16 '18 at 09:05
  • 1
    @OrtwinGentz Have you found an alternative for IOS 12 ? – the Reverend Aug 27 '18 at 22:54
  • 3
    @theReverend as Bill mentioned, implementing the `willPresent` delegate is all that's needed. – Ortwin Gentz Aug 28 '18 at 15:44
0

UNUserNotificationCenter.current().requestAuthorization's completion Handler works asynchronously (the method is handled in different thread). That's why "if isGrantedNotificationAccess.." statement in your code was read before completionHandler was completed.

There are some ways to resolve the issue. One is to use NotificationCenter to notify the end of the requestAuthorization method to HomeViewController (see the example below).

import UserNotifications

class HomeViewController: UIViewController{

let notification = Notification.Name("requestAuthorizationComplete")

override func viewDidLoad() {
    super.viewDidLoad()

    // Register self as Observer to receive notification
    NotificationCenter.default.addObserver(self, selector: #selector(self.triggerNotification), name: notification, object: nil)

    UNUserNotificationCenter.current().requestAuthorization(
        options: [.alert,.sound,.badge],
        completionHandler: { (granted,error) in
        NotificationCenter.default.post(name: self.notification, object: nil)
    })

}

func triggerNotification(notification:NSNotification?){
 // this function will be called once requestAuthorization is complete
}
cat
  • 1
  • 3
  • No change. Still it doesn't get triggered – Jay Dec 29 '16 at 05:47
  • i just fixed one typo notification --> self.notification and it works fine on my side. Please try this. – cat Dec 29 '16 at 05:54
  • Weird, mine doesn't get fired still. Could you please post the triggerNotification function of yours as well? – Jay Dec 29 '16 at 06:03