NSNotification when device time changes (minutes)? - iphone

Is there a way I can easily set up a notification when the minutes change on the system time for iOS devices?
I need to do some UI updates for time changes. I'd like the UI to update exactly on minute changes, not just every 60 seconds through an NSTimer trigger.

There are no notifications provided by the API but you could roll your own by having a background thread polling the system time and then sending a custom notification to the UI on the main thread.
However, I wouldn't bother. You can't manage time "exactly" on any device with a software UI. The best you can do is get the UI updates to occur below the threshold of user perceptions. Humans can't really perceive time intervals of less than 100-200 milliseconds (1/10th second). Any UI more precise is wasted. A NSTimer can very reliably hit a 100 millisecond window as long as some other part of the app doesn't hang or bog.
Unless you've tested the interface using a NSTimer and found it wanting, I wouldn't go looking for adding complexity.

Related

Is it possible to run a scheduled timer in a suspended app?

I've read several posts on creating a timer that runs in the background. Is it possible to create a scheduled timer that will continue to run once the app has been suspended/terminated?
Apple's own timer achieves this, but it's not clear how. I am guessing they send a local notification for the timer expiry, and maybe they undertake a date object comparison if the app is brought to the foreground while still in the countdown period. Is this a correct assumption? Any pointers would be helpful.
In short, what you're looking to do is not possible - since the amount of time your app is allowed to run in the background is limited to ~3 minutes. Look at this answer for more details.
You could achieve your goal through the use of a push notification, but that would require a server and won't guarantee it is received at the perfect time.
You might also want to look at this question
It also appears based on this answer that you cannot set a timer in the standard clock app either.
TLDR - You can't create a timer app.

iPhone alarm using repeated local notifications

I'm trying to add an in-background alarm clock feature to an app I'm developing.
I have read up on the UILocalNotification object and its use, and am aware that it is limited to 30 seconds of audio.
I was thinking of scheduling multiple notifications (say, 5 of them) spaced 30 seconds apart to mimic continuous play, but the problem with this approach is that if the user hits Close, I won't be able to cancel any of the subsequent notifications.
As far as I know, it is impossible to remove or hide the Close button without hiding the notification entirely (i.e., setting the alertBody property to Nil).
So, I thought I might use the repeatInterval property to cause the notification to pop up every 30 seconds, but it seems that I can only set the interval to one minute or one second, and nothing in between.
The feature is meant to allow the user to choose between music and beeps for alarm audio; it seems I may have found a way to do the beeps - setting the repeatInterval to one second, create a second's worth of beeps (which would need to be timed to cleanly repeat) and use that as the notification sound.
However, for the music, this approach limits me to playing 30 seconds of audio, followed by a 30-second gap, followed by 30 seconds of audio, and so on.
I know that there is no straightforward solution here, from my reading of other posts and resources; no third-party app has access to the same functionality as the built-in alarm clock. I am hoping that someone has found a workaround or thinks of something really clever.
UPDATE: I have found that the repeatInterval doesn't help me in this case, as I can't cancel the repetitions without launching the app.
For the time being I have decided not to use a notification as an alarm per se, but have changed the feature to be a reminder (more along the lines of what the notification is intended for).
If I come up with a way to implement user-friendly, reliable alarm functionality to an app, I will update this post.
I am afraid you cannot accomplish this..reason being as you stated the 'Close' button. You won't be getting any call back in the app if Close button is tapped. Further even if you present notifications every 30 seconds, then there will be multiple notifications on the screen which user has to view or close. So the user experience will be crappy. I would recommended making it clear to the users that they can not set alarm with a custom sound more than 30 seconds.

iPhone running periodical process in the background - battery optimized way

I want to run a specific task in the background. This task takes few seconds to complete (it writes some GPS location data to a file). This task should run once every 1 hour.
As I understand from the SDK, I do not have a way to INITIATE something in the background unless I run Location Services forever. When this service runs, it gives me an event from time to time, and I'm able to run my code during these calls. I tried it, and even with the minimal precision possible, my battery goes down very quickly.
So, I'm looking for a way to run Location Services for few seconds every hour. All the rest of the time I do NOT want to run Location Services and I do NOT want to use the battery.
Can you help here please?
Thanks,
Gena
What do you actually want to know every hour? Are you trying to determine the location accurately, or just determine if the phone has moved significantly? startMonitoringSignificantLocationChanges will notify you when the phone moves "significantly" (which generally means changing cell towers). In cities this can happen quite often. startMonitoringForRegion:desiredAccuracy: will only notify you when you move outside of a given radius.
startMonitoringSignificantLocationChanges is pretty cheap. It mostly relies on the cell antenna, which is generally on anyway. If it fires more than once an hour, you could always just skip processing and return. But there's no guarantee that you'll be called once an hour, particularly in rural areas.
If you are a VoIP app, then you may register a periodic "checkin" interval when you may run code. But you cannot do this for location apps.
Have you profiled your code using the Energy Diagnostics instrument? What's actually eating time and power? Are you chewing on the radio, the CPU, the disk?
EDIT
When the app dies, Significant Changes still continue to run and leave a small direction arrow icon next to the percentage on the top toolbar of the iPhone. My users complain that the icons remains after killing the app
After the app dies, if you were registered for significant changes, you would expect to be relaunched in response to them. If you want to unregister in cases where you are terminated, you can add stopMonitoring... to your applicationWillTerminate: method. This isn't guaranteed to be called, but it is a good thing to do, and I believe it will be called if the user terminates you directly and you were not suspended (haven't tested that).
Again, significant location changes should be extremely cheap in terms of battery life as long as there is cell coverage. They should not force the GPS to stay on.
Your best bet is to use significant location changes ... here are some links you can get help from -
http://developer.apple.com/library/ios/#documentation/CoreLocation/Reference/CLLocationManager_Class/CLLocationManager/CLLocationManager.html
http://www.switchonthecode.com/tutorials/getting-your-location-in-an-iphone-application
http://longweekendmobile.com/2010/07/22/iphone-background-gps-accurate-to-500-meters-not-enough-for-foot-traffic/#more-480

How do I get a codeblock to run on the iPhone once every 24 hours at midnight if my app is suspended (multitasking)

Was reading through the iOS4 documentation for multitasking, and couldn't figure it out.
I basically need to update the badge count on my app's icon after midnight each day as long as the app is running in suspended mode (with multitasking).
I know this has to be possible, just can't figure out the best way to do it.
Thanks.
iOS "multitasking" is very specific. There's an important distinction between states here:
Suspended: Your app resides in memory, but does not receive any execution time. This is really only useful for fast app switching.
Background: In a few particular cases, you can request that the OS to run your app in the background. (Playing audio, location, finishing a long task, voip.)
So, the short answer to your question is, "you can't."
Here are a couple useful links on iOS multitasking, such as it is.
Understand an Application's States and Transitions
Executing Code in the Background
You could use a UILocalNotification to set the badge (without an alert) but you can't increment the badge because you're app does not have the opportunity to execute any code when the notification fires.
You can schedule up to 64 notifications in advance, one at midnight for the next 64 days, each one setting a new badge number. It would make a lot more sense to schedule a repeating notification but since your app can't execute code it can't increment the badge number that doesn't work.

Timer running while on home screen iPhone - Objective C

I am interested in building a Timer Based game such as mafia wars or soemthing like that. I'm stuck on one question.
What would be the best way to retain a timer, even if the app is closed?
Should I do this based on the Device Clock? or should I set a time to a server, and get the time when the device starts up?
If any one knows a better way for this,
let me know.
Thanks.
#lessfame
I'll interpret your question as "What's the best way to measure elapsed time between app launches?" instead of "How do I make a timer fire when my app is closed?".
There's no reliable and accurate way to measure time when the device is powered off (remote servers might not be reachable, astronomical measurements might not be possible if it's cloudy, ...). Don't bother.
That said, most CF/NS APIs use CFAbsoluteTime/NSDate (namely, CFRunLoopTimerGetNextFireDate() and -[NSTimer fireDate]). I'm not sure what they do if the system clock changes.
You can use mach_absolute_time() (and it's used internally by some things), but that's just system uptime, so it fails if the phone reboots. I'm not sure if you can get the boot UUID in order to find out if the phone has rebooted.
At the end of the day, CFAbsoluteTimeGetCurrent() or (equivalently) [NSDate date] is probably enough; just make sure that your app behaves sensibly if the time suddenly changes by a day or two in either direction.
Yes, the user can game the system by setting the system clock. You can mitigate this to some extent by occasionally syncing with the server, and keeping track of game time elapsed between syncs. If the difference between elapsed game time and server time is small, then just speed up or slow down the game appropriately to bring elapsed "game time" to real time. If the change is large, you can restore from the last save point on the server, or make the user wait until the elapsed game time has elapsed in server time, or a bunch of other things. This means you can't start playing until the initial sync, but the user has to be online to download the app anyway, so it's not a major problem.
If you only need to retain the time and show how much time elapsed since the game was closed (i.e. you don't need to notify the user when the time is up), you can use the [NSDate timeIntervalSinceNow] method to determine the amount of milliseconds that passed between two times.
If you are saying you want to just know time elapsed since some event, all you do is log the initial time, and then log the final time and compare the difference.
If you need a countdown timer to some event then what you do is set up a local push notification set to go off at the end time.