iOS 9 cancelLocalNotification problems - ios

I've had an app on the App Store for over a year now which uses UILocalNotifications to act as reminders. The UILocalNotifications use the repeatInterval, set to NSCalendarUnitMinute, to keep reminding the user of whatever they wanted to be reminded of.
Everything was fine with the app when building against iOS 7/8 but now that I've started to build it against iOS 9 I'm having epic issues using [[UIApplication sharedApplication] cancelLocalNotification: notification] to stop previously scheduled notifications.
I've checked the number of notifications in [[UIApplication sharedApplication] scheduledLocalNotifications] before and after cancelling a notification to verify that the count does get decremented, but when it comes round to the time that the notification would have hit its repeatInterval the notification cheerily pops up its head to haunt me...
I've tried all sorts of things... cancelling individual notifications, [[UIApplication sharedApplication] cancelAllLocalNotifications], [UIApplication sharedApplication].scheduledLocalNotifications = [NSArray array] but nothing was doing the trick at all...
A number of times I thought I'd solved the problem but then it would keep rearing its head, generally on older notifications I'd scheduled, though always seemed fine on ones I'd just recently setup.
Just now I managed to get rid of a lingering, un-cancellable notification by force quitting the app after an attempt to cancel it... which is hardly an elegant solution for end users other than myself...
Has anyone else had these kinds of issues with local notifications, possibly specifically those that are setup to auto-repeat?
For the sake of it I'll reference this similar post which could technically be called a duplicate but I'm posting this new question as the other one isn't getting any interest and needs my somewhat different situation to be described and solved! (PS if you get this question closed as a duplicate I will cry.. and no one wants to see that, right?)

Related

UILocalNotification in iOS 9 of iBeacon app tips sound 2 times but just one notifaciton in list

It's very strange in iOS9 again. This one is in my iBeacon app. When i had sent location notification just one time but got the tips sound 2 times in - (void)locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region.
If i send local notification outside the didDetermineState or in iOS8 and it tips sound just one time.
Very weird and whatever i use presentLocalNotificationNow or scheduledLocalNotifications and all got the same problem.
I will go crazy for iOS9.....
Finally i got the answer. If i try to execute registerUserNotificationSettings twice in iOS9. YES, i will got tips sound twice in one local notification.
Mabybe it's a bug of iOS9.
ever since ios8 some additional internal filtering is applied. We here noticed the same with many of our apps :/
we never found out the logic or any kind of workaround...

What iOS events can trigger an application that is suspended/not running?

Does anyone know if there is a defined list of actions/events that will cause a suspended/not running application to become active?
For example, if you call [[UIApplication sharedApplication] beginReceivingRemoteControlEvents], pressing an audio control command on the control center will resume/start the app in the background. To prevent this from occurring, [[UIApplication sharedApplication] endReceivingRemoteControlEvents] needs to be called before the app is terminated or sent to the background.
Are there are other system-level events which can activate the app like this?
There are many triggers that can activate "dead apps". These include but not limited to:
-Push Notifications
-GameCenter Requests
-Significant Location Changes
-iCloud (Although hard to do)
-iBeacon
-Passbook location sensor
-and many more
Hope that helped

"[[UIApplication sharedApplication] openURL:url]" - Can't Open more than two to four URLs without killing my app

I am using [[UIApplication sharedApplication] openURL:url] to open social media URLs in an app. However, I can't seem to open more than two to four URLs before my app gets killed (app ended unexpectedly). I also notice that when I call the above mentioned method, my memory usage is jumping significantly (I was hoping this would not be the case).
I tried to open the exact same URLs from mail.app, and I can keep opening the URLs without mail.app being killed. So definitely something is wrong with my app.
Question 1: Any input on how can I avoid increasing memory usage when I call [[UIApplication sharedApplication] openURL:url].
Question 2: Why is mail.app not getting killed, while my app is killed?
Many thanks!
Upon researching another question on stack overflow and following suggestion to remove NSLog (not many of them in my app), things seem to work just fine and my app is not getting killed. I am logging this for any future reference for other readers. If you're getting a message that your app is killed due to MEMORY PRESSURE, try removing NSLog from the app and see if that helps. It helped me! Here is the reference to the other thread: link

Repeating a task when app is in background (e.g. pull something from a server), without APNs

Is there a good, Apple-approved alternative to using push notifications to trigger an app to run some code (in particular: pull new messages from a server) in a regular interval?
Disguising as VoIP app is not a good option (won't be approved, see iPhone: repeating background task)
I cannot use location updates, it should work if the user does not move around
In the simulator, using beginBackgroundTaskWithExpirationHandler with dispatch_async gives you 10 minutes of background time, and I found out that if the background "restarts itself", the backgroundTimeRemaining property always seems to be reset to 10 minutes. Here's the code.
- (void) work
{
UIApplication *application = [UIApplication sharedApplication];
NSLog(#"bg %# (T-%.1f seconds)",
[NSDate date],
[application backgroundTimeRemaining]);
sleep(10);
[application endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
[self startTask];
}
- (void)startTask
{
UIApplication *application = [UIApplication sharedApplication];
_bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"expired at %#", [NSDate date]);
[application endBackgroundTask:_bgTask];
_bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,
0),
^{ [self work]; });
}
- (BOOL) application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
/* ... */
[self startTask];
/* ... */
}
Would that be an accepted practice to run something in the background? I mean, most of the time I would just sleep(...) until I want to repeat a network request or do something useful, but the app would never really enter full background mode. Does anyone have experience with this approach? Hint: Only tested on simulator without other running apps.
The Apple-approved alternatives are listed in https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
Looking at "Table 3-1 Background modes for apps", the two relevant alternatives for repeatedly getting info from a server are "Background fetch" or "remote-notification".
"remote-notification" is push notifications, which you say you don't want to use.
Therefore, "Background fetch" is the relevant choice. For example, see https://blog.newrelic.com/2016/01/13/ios9-background-execution "Downloading remote content opportunistically".
However, this does not give you (the developer) the degree of control you would have in Android. There is "setMinimumBackgroundFetchInterval", but notice that this is a MINIMUM: iOS decides when to call into your app for the next background fetch. (Apple is focused on overall battery usage and device responsiveness; once your app is in the background, design to work gracefully with however little attention it is given.)
NOTE: If the user kills your app, "Background fetch" will be killed with it. This is by design. (And is a good thing, from the user's viewpoint: most apps should stay dead if killed.)
Consider using a combination of "push notification" (remote-notification) and "Background fetch". For example, if a user permits "push notifications" by your app, then do one push daily, with a text notification to user. If they open that notification, that will open your app. Then begin the data fetching. If they hit Home button, use "Background fetch" to continue data fetching periodically through the day.
Users who are very battery-conscious may kill all their apps periodically. If they don't want to be bothered by your app today, they will ignore or delete your app's push notification. Consider this a good thing: you won't annoy users by draining battery on days that they aren't actively using your app.
Users who like to have tight control over what is running on their phone WILL NOT permit push notifications for your app. (For instance, I hate to receive daily text notifications. Don't call me, I'll call you.) In this case, once your app is killed, there is nothing that you can do (since push notification is the only way to resurrect your dead app, and I, the user, have said "No" to that). Be sure to consider how you will serve such users. (Your content may be stale when they first re-open your app.)
You can't do this on a normal iphone. And if you found out a way to do it, Apple would eventually fix the loophole and reject your app.
I don't know about jailbroken iphones, I suspect it might be possible on them somehow.
I think you can use "local notifications" to trigger something to occur at a specific time.
https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/SchedulingandHandlingLocalNotifications.html#//apple_ref/doc/uid/TP40008194-CH5-SW1

Set default iOS local notification style for application

Starting with iOS 5, there are two notification styles: banner and alert (the "old" style). A user can set which style to use for each application in the settings. However, the default now seems to be that notifications are displayed banner style.
I'm using local notifications for reminders about events that will happen "now". A banner disappears shortly after it appeared (and it's not obvious enough that one can tap it), so for these notifications it would be desirable to have the alert style notifications as those stay on screen until the user decided on an action (ignore or go to app).
Is there a way either through code or for example Info.plist entries to tell iOS that the alert style notifications should be used by default (as long as the user hasn't configured something else)?
Update: The absence of information/documentation is not enough for me to have this settled. I want either something like a forum/blog post from someone with authority (Apple employee or someone along the lines of Erica Sadun) saying it's not possible, or if it is possible then I want the solution. A workaround like "ask the user to change the setting" isn't good enough either.
I would like to add something, since I've opened a TSI and somehow I asked about this and have been answered. From Quinn "The Eskimo!":
"This depends on you mean. You have some control over how the notification appears based on how you set the UILocalNotification properties (things like alertBody, soundName, and so on). However, if you're asking about the way in which those properties are interpreted (the things the user can customise in Settings > Notifications), those are user preferences and not exposed via any API."
I have an alarm app for which I also need this functionality. Under iOS5 if the user is using another app when it goes off then the banner appears. Consequently I spent a lot of time browsing for a solution.
However, it's not possible to control the style of alert generated by a UILocalNotification I'm afraid :(
You can see from the class reference that there's no provision for it:
http://developer.apple.com/library/IOs/#documentation/iPhone/Reference/UILocalNotification_Class/Reference/Reference.html
Or in the plist:
http://developer.apple.com/library/ios/#documentation/general/Reference/InfoPlistKeyReference/Articles/iPhoneOSKeys.html
Best thing to do is tell the user what to do to change the settings.
You probably won't find 'authoritative' from your peers here, you should better ask directly to Apple; and the question has already been asked several times on theirs forums and not answered...
The HIG programming guide - http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/MobileHIG/TechnologyUsage/TechnologyUsage.html#//apple_ref/doc/uid/TP40006556-CH18-SW1 -
"iOS apps that support local or push notifications can participate in
Notification Center in various ways, depending on the user’s
preferences."
That last sentence is the only 'authoritative hint' i found.
The USER'S preferences <= you can't force the user ('s preferences).
Period.
This design choice is clearly the Apple Way (applications' playground IS limited, to ensure the best user experience possible)
As for more authority... maybe shouting ?
NO YOU CAN'T CHOOSE YOUR NOTIFICATIONS DISPLAY STYLE, IT'S THE USER'S CHOICE
Just kidding...
Anyway, a workaround might be to provide a way in your application - hint/ tutorial - to push the user to change the alert style himself...
good luck !
Obviously you don't like hearing no for an answer, but, no.
You can use this line to query the current settings for notification style:
UIRemoteNotificationType* enabledTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
You can check the enabledTypes and then instruct the user to change the notification style in the settings.
have you tried
[[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
in your didFinishLaunching method, this won't help those updating but should enable alerts for those first installing

Resources