UNLocationNotificationTrigger not triggering - ios

I'm trying to create a notification which triggers when entering a region using UNNotificationLocationTrigger. I implemented it like this:
let destination = //destination is added by user through interface//
let notification = UNMutableNotificationContent()
notification.title = "You've reached your destination"
notification.body = "Some"
notification.sound = UNNotificationSound.default()
let destRegion = CLCircularRegion(center: destination, radius: 1000.0, identifier: "DistanceToDestination")
destRegion.notifyOnEntry = true
let trigger = UNLocationNotificationTrigger(region: destRegion, repeats: false)
let request = UNNotificationRequest(identifier: "destAlarm", content: notification, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: { error in
if error == nil {
print("Successful notification")
} else {
print(error ?? "Error")
}
})
I tried it on a real device and walked around. It worked 2 times perfectly when I entered the region (I checked it with a map and region as circle overlay in map). But after that all other attempts failed.
EDIT:
For those reading the comments. It's not working again. So it seems to be pretty inconsistent. If somebody know if it's a bug or know how to fix it I would be very grateful.

First of all, you should call locationmanager.startupdatinglocation
Second of all, you should change the trigger so that repeats = true

Related

Triggering several notifications in Apple Watch in short period of time makes them grouped

Im making a standalone Apple Watch app, testing on device, and its meant to play several bells with vibration (app can be closed and alerts should play) in a period of like 5 seconds or so, Im using local notifications for this and no matter what I try I only hear the first notification bell or if I extend in time maybe 2 bells, in the past alerts summary these consecutive notifications are listed but the bells are not played. I know there is a way to do this as I saw an app that plays several bells like this and is standalone Apple Watch app too. Im using swift, how can I do that? Thanks for any help
I made a separate code only to trigger some alerts in 10 seconds from now to show better my issue here:
import SwiftUI
import UserNotifications
struct ContentView: View
{
var body: some View
{
VStack
{
Button("Request Permission")
{
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success {
print("All set!")
} else if let error = error {
print(error.localizedDescription)
}
}
}
Button("Schedule Notification")
{
let content = UNMutableNotificationContent()
content.title = "First notification"
content.subtitle = "Whatever"
content.sound = UNNotificationSound.defaultCritical
// show this notification 10 seconds from now
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)
// choose a random identifier
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
//----------/
var content2 = [UNMutableNotificationContent](repeating: UNMutableNotificationContent(), count:100)
var trigger2 = [UNNotificationTrigger](repeating: UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true)
, count:100)
var request2 = [UNNotificationRequest](repeating: UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger),count:100)
// add notification request
UNUserNotificationCenter.current().add(request)
for i in 0..<100
{
content2[i] = UNMutableNotificationContent()
content2[i].title = "Chained notifications"
content2[i].subtitle = "whatever"
content2[i].sound = UNNotificationSound.defaultCritical
//content2[i].interruptionLevel = .active
content2[i].interruptionLevel = .critical
content2[i].categoryIdentifier="category\(i)"
content2[i].threadIdentifier="asadasaa\(i)"
trigger2[i] = UNTimeIntervalNotificationTrigger(timeInterval: 10+Double(i/4), repeats: false)
// choose a random identifier
request2[i] = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request2[i])
}
//-----------/
}
Button("Stop")
{
UNUserNotificationCenter.current().removeAllPendingNotificationRequests()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I tried several intervals between notifications, making them more separate or closer to each other and only first one plays or 2 or more bells if there is some longer intervals but most are grouped and only hear like one every second at the most I think, I read somewhere these are meant to be payed in 0.9 seconds at the shortest time but as said I have seen an app able to do this so there has to be a way
I was suggested to use different thead or so, but didnt work, tried other parameters of this too like to change revelance or so but nothing worked
The issue may work the same in iPhone if you are more familiar with it, so if you know a workaround for this let me know

How Do I Remove The Notification From The Screen After Being Clicked On

For a few months, I have been working on an app which uses local UNNotifications to achieve the grand goal. I coded this app using Swift 4, therefore aiming it towards distribution on the iOS App Store. As I was testing my app out, I noticed that after I clicked on one of the notification actions (which was not "cancel"), or if I just tapped on the notification in general, the app would open up (which is intended), but the notification would remain on the screen. Is there any possible way to remove the notification from the screen after already tapping on one of the actions programmatically? Below is the code where I schedule the notification:
let action1 = UNNotificationAction(identifier: "go", title: "Go", options: [.foreground])
let action2 = UNNotificationAction(identifier: "cancel", title: "Cancel", options: [.destructive])
let actionsCategory = UNNotificationCategory(identifier: "actions.category", actions: [action1, action2], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([actionsCategory])
//Queue the notification alert
let content = UNMutableNotificationContent()
content.body = "Interesting day notification!"
content.sound = UNNotificationSound.default()
content.setValue(true, forKey: "shouldAlwaysAlertWhileAppIsForeground")
content.categoryIdentifier = "actions.category"
// if (pinNumber.text) != nil{
// }
content.userInfo = ["Name": namePerson.text ?? "", "Pin": Int(pinNumber.text ?? "") != nil ? pinNumber.text! : ""]
//trigger
let triggerDate = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute], from: datePicker.date)
let trigger = UNCalendarNotificationTrigger(dateMatching: triggerDate, repeats: false)
//scheduling
let identifier = id // set same id as task
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
center.add(request, withCompletionHandler: {(error) in
if let error = error{
print(error)
}else{
print("saved alert")
}
})
I don't see anything in your code that would cause that behavior. This sounds to me like either an iOS bug, or there is something weird about the notification permissions/settings of the particular device (or simulator) for your app. Go into the notifications sections of the Settings app and see what the settings are for your app.

How to show multiple local notifications

Background:
Im writing an application where a bot sends you messages. These messages can be received as local notification.
The Problem:
When the bot sends multiple notifications within a short span of time (1 second between each message), the notification center will only show one message. I will hear the notification sound every time I expect to, But i will still only see the first message.
Relevant code:
func postUserNotification(content: String, delay: TimeInterval, withDictionary dictionary: [String:String] = [:]) {
let notificationContent = UNMutableNotificationContent()
notificationContent.body = content
notificationContent.userInfo = dictionary
notificationContent.categoryIdentifier = "message"
let dateAfterDelay = Date(timeIntervalSinceNow: delay)
let dateComponents = Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: dateAfterDelay)
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: false)
let identifier = "identifier" + "\(NotificationManager.incrementor)"
let localNotification = UNNotificationRequest(identifier: identifier, content: notificationContent, trigger: trigger)
UNUserNotificationCenter.current().add(localNotification){ (error : Error?) in
if let theError = error {
print("the error is \(theError.localizedDescription)")
}
}
}
Nothing wrong with your code :
Like you wrote in your question, this is mentioned in the Apple Docs:
If you are sending multiple notifications to the same device or
computer within a short period of time, the push service will send only
the last one.
https://developer.apple.com/library/content/technotes/tn2265/_index.html#//apple_ref/doc/uid/DTS40010376-CH1-TNTAG23

Geofence alerts/local notifications not waking up locked phone when triggered

I'm making an app that used circular regions for geofences. When the phone is active or the app is open, the geofence notifications are working fine in both simulator and device (iPhone 6 running 10.3.1).
In the simulator it works fine; When the user enters a region, it wakes up, makes a sound and shows an alert on the lock screen.
On the phone, the "didEnterRegion" delegate calls are made when entering the region (I log some messages) but the phone is not making an alert and waking up. When I push the home button once, I can see the alert on the lock screen, but I want it to wake up and show the alert instantly - like when I get a message. It works in the simulator, so I wonder what could be wrong? It has worked for me a few times, where the alert was shown on both the phone and my watch, but 95% of the time it's not working - the notifications are generated but only visible if I manually wake up the phone.
How to fix this?
Here's the code I use for creating the local notification:
// https://blog.codecentric.de/en/2016/11/setup-ios-10-local-notification/
let location = CLLocation(latitude: item.coordinate.latitude, longitude: item.coordinate.longitude)
GeoTools.decodePosition(location: location) {
(address, city) in
let content = UNMutableNotificationContent()
content.title = "Camera nearby!"
content.subtitle = item.id
content.body = "\(address), \(city)"
content.categoryIdentifier = Constants.notificationCategoryId
content.sound = UNNotificationSound.default()
content.threadIdentifier = item.id
// FIXME make action for clicking notification
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.001, repeats: false) // FIXME HACK
let request = UNNotificationRequest(identifier: "camNotification", content: content, trigger: trigger)
let unc = UNUserNotificationCenter.current()
unc.removeAllPendingNotificationRequests()
unc.add(request, withCompletionHandler: { (error) in
if let error = error {
print(error)
}
else {
print("completed")
}
})
}
Here is some code that I just verified wakes the device when notification is presented:
let message = "CLRegion event"
// Show an alert if application is active:
if UIApplication.shared.applicationState == .active {
if let viewController = UIApplication.shared.keyWindow?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
else {
// Otherwise app is in background, present a local notification:
let content = UNMutableNotificationContent()
content.body = message
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "message"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1.0, repeats: false)
let request = UNNotificationRequest(identifier: "com.foobar", content: content, trigger: trigger)
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
Really the only diff is that I don't call removeAllPendingNotifications() so if you must remove notifications I wonder if removePendingNotificationRequests(withIdentifiers identifiers: [String]) might be more precise?

How to display a message on top?

I'm new to WatchKit development. I would like to display a message regardless of what app is currently being used or whether the watch is active or not, like how the built-in Timer app shows the label "Timer Done". The user should then be able to click an "OK" button and dismiss the message.
I have tried using both alerts and modal views, but showing them programmatically still requires my app to be active. Using the notifications system is not a viable solution because that would rely on an iPhone.
I've been stuck on this for many hours, any insight would be helpful, thanks.
You need to ask permission in your iOS App first:
UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.badge,.sound])
{ (granted, error) in
if !granted
{
print("User did not give permissions to send notitications...")
}
}
Then in your watchOS App you can create a notification for some time in the future, make sure you give it a UUID (this may be a bug in watchOS3):
let content: UNMutableNotificationContent = UNMutableNotificationContent()
content.title = "Title"
content.subtitle = "Subtitle"
content.body = "message"
content.sound = UNNotificationSound.default()
content.categoryIdentifier = "aCategory"
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: duration, repeats: false)
let id: String = WatchNotify.getUUID()
let request = UNNotificationRequest.init(identifier: id,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request)
{
(error) in // ...
}
....
class func getUUID() -> String
{
let uuidObj = CFUUIDCreate(nil)
let uuidString = CFUUIDCreateString(nil, uuidObj)!
return uuidString as String
}

Resources