5

I created a notification with two actions. One of my actions is called "Cancel", while the other is called "Call". How do I make the "Call" action run a URL that is in a comment that I added to my code. Here is my code:

  func notificationFires(){

    /**
     URL Code:

     if let url = URL(string: "tel://") {
     UIApplication.shared.open(url, options: [:])
     }


**/

    let call = UNNotificationAction(identifier:"call", title:"Call", options:[.foreground])
    let cancel = UNNotificationAction(identifier: "cancel", title: "Cancel", options: [.destructive ])
    let category = UNNotificationCategory(identifier: "category", actions: [call, cancel], intentIdentifiers: [], options: [])
    UNUserNotificationCenter.current().setNotificationCategories([category])

    let notification = UILocalNotification()
    notification.category = "category"
    // 2

    notification.soundName = UILocalNotificationDefaultSoundName
    notification.fireDate = datePicker.date

    // 3
    if textField.text == "" {

        notification.alertBody = "You have a call right now!"

    }
    else{

        notification.alertBody = self.textField.text

    }
    // 4
    notification.timeZone = NSTimeZone.default
    // 5
    // 6
    notification.applicationIconBadgeNumber = 1
    // 7

    func application(application: UIApplication!, handleActionWithIdentifier identifier:String!, forLocalNotification notification:UILocalNotification!, completionHandler: (() -> Void)!){

        if (identifier == "call"){
            if let url = URL(string: "tel://2162964785") {
                UIApplication.shared.open(url, options: [:])
            }
        }else if (identifier == "cancel"){

        }

    }

    UIApplication.shared.scheduleLocalNotification(notification)



    func application(application: UIApplication,  didReceiveLocalNotification userInfo: [NSObject : AnyObject],  fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
        print("Recieved: notification")



        let center = UNUserNotificationCenter.current()
        center.removeDeliveredNotifications(withIdentifiers: ["notification"])




    }

}
krish
  • 159
  • 1
  • 12
  • perhaps the following would be helpful http://useyourloaf.com/blog/openurl-deprecated-in-ios10/ https://stackoverflow.com/questions/38964264/openurl-in-ios10?rq=1 – CuriousRabbit Jan 17 '17 at 16:20

1 Answers1

1

Assuming your notification is working correctly, you can conform to UNUserNotificationCenterDelegate to handle the "call" action.

Something like:

 func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        if response.actionIdentifier == "call" {
            let body = response.notification.request.content.body

            if let url = URL(string: "tel://\(body)") {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
    }

The body constant would be set to the phone number that you want to "open".

Also, its important to note that this has to be tested on an actual device. Opening a tel scheme does nothing in the simulator.

UNUserNotificationCenterDelegate API Reference: https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate

EDIT:

You do not call the delegate method. Instead you implement it. The delegate method is called by the UNUserNotificationCenter.

To get this working, its important to ensure that you set the UNUserNotificationCenter.current() delegate property to a class that will conform to the UNUserNotificationCenterDelegate protocol.

For example, if you are handling your notification in your AppDelegate, you may have something like the following method:

func callNotification() {
    let center = UNUserNotificationCenter.center()

    // TODO: - Create your actions, category, content, trigger and request...

    center.delegate = self // Important!

    center.removeAllPendingNotificationRequests()
    center.add(request, withCompletionHandler: nil)
}

The method above would be responsible for defining your notification and scheduling it. For brevity, I have left out all of the code that would define the notification since you indicated that this is working. Instead you should note that the delegate property is being set to self.

Then in an extension, you would make the AppDelegate conform to the UNUserNotificationCenterDelegate and implement the required methods.

extension AppDelegate: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        if response.actionIdentifier == "call" {
            let body = response.notification.request.content.body

            if let url = URL(string: "tel://\(body)") {
                UIApplication.shared.open(url, options: [:], completionHandler: nil)
            }
        }
    }
}

Now because your AppDelegate conforms to the UNUserNotificationCenterDelegate protocol and you set self (AppDelegate) as the UNUserNotificationCenter's delegate, your implementation of the userNotification(_:didReceive:withCompletionHandler:) method will be called.

Ryan H.
  • 2,543
  • 1
  • 15
  • 24
  • @Krish Did you get an error? Did you test on the simulator or an actual device? Is the notification appearing? – Ryan H. Dec 20 '16 at 05:49
  • No I did not get an error, and I did test it on my actual phone. The notification does pop up, although when I tap on the "Call" button, all it does is bring me into the app instead of running the URL to call someone. – krish Dec 21 '16 at 15:25
  • @Krish It should bring you to your app and the `userNotificationCenter(_:didReceive:withCompletionHandler:)` method should handle the opening of the `tel` scheme. Is the delegate method getting called? – Ryan H. Dec 21 '16 at 18:21
  • Where would I need to call the delegate method? – krish Dec 22 '16 at 13:48
  • And how do I call the delegate method? – krish Dec 22 '16 at 13:51
  • @krish I have updated my answer with details on how to implement the delegate. – Ryan H. Dec 22 '16 at 17:28
  • NOTE: I setup my whole notification in ViewController.swift – krish Dec 22 '16 at 22:04
  • Is it okay if I put this in my notificationFires() function in my ViewController – krish Dec 23 '16 at 02:30
  • @krish That would be fine. However, you should ensure that your delegate object is set early on in your app's lifecycle, preferably in your `AppDelegate`'s `application(_:willFinishLaunchingWithOptions:)` or `application(_:didFinishLaunchingWithOptions:)` methods. See Apple's important note [here](https://developer.apple.com/reference/usernotifications/unusernotificationcenterdelegate). – Ryan H. Dec 25 '16 at 21:15