Get the time to "run" in iOS - iphone

I've read a guide about how to make a clock, in iOS. And that works like it should and all that, but i want to go further and get the clock to update each minut. So it's no longer "static", so if you open the application 12:16 am, and let it run it should automatically update each minut(12:17 am, 12:18am etc.).
This is the code the guide provided me with,
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
I've tried and tried to look through google and stackoverflow, but just can't find anything.
Thanks in advance, Oluf Nielsen.
EDITED : My code now looks like this
-(void)clock
{
NSDateFormatter *datoVar = [[NSDateFormatter alloc] init];
[datoVar setDateFormat:#"hh:mm"];
LabelKlokken.text = [datoVar stringFromDate:[NSDate date]];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self clock];
tid = nil;
tid = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(clock) userInfo:NULL repeats:YES];
}

You can schedule an NSTimer to check for time every 60 seconds.
dateTimer = [NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];
put your code in updateTime method. Better yet, check it every second, because it could happen that you switch time in 59th second of each minute thus being 59 seconds behind...
Remember to invalidate the timer once you want to quit updating so your app doesn't crash when you switch views or something.
[dateTimer invalidate];
dateTimer = nil;

Related

How would I make my timer run in the background and then send a local notification?

For some reason my timer only runs in the foreground. I've searched here for solutions but I couldn't find any good ones. My timer uses Core Data and my timeInterval is saved after every decrement. Also, I'm sending a UILocalNotification but that doesn't work. I'm assuming it doesn't send a alert view if its in the foreground..Well this is what I have now:
-(IBAction)startTimer:(id)sender{
if (timer == nil) {
[startButton setTitle:#"Pause" forState:UIControlStateNormal];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerAction:) userInfo:nil repeats:YES];
} else {
[startButton setTitle:#"Resume" forState:UIControlStateNormal];
[timer invalidate];
timer = nil;
}
}
-(void)timerAction:(NSTimer *)t
{
if(testTask.timeInterval == 0)
{
if (self.timer)
{
[self timerExpired];
[self.timer invalidate];
self.timer = nil;
}
}
else
{
testTask.timeInterval--;
NSError *error;
if (![self.context save:&error]) {
NSLog(#"couldn't save: %#", [error localizedDescription]);
}
}
NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
NSString *string = [NSString stringWithFormat:#"%02u:%02u:%02u",
seconds / 3600, (seconds / 60) % 60, seconds % 60];
timerLabel.text = string;
NSLog(#"%f", testTask.timeInterval);
}
-(void)timerExpired{
UILocalNotification* localNotification = [[UILocalNotification alloc] init];
localNotification.alertBody = #"Time is up";
localNotification.alertAction = #"Ok";
localNotification.timeZone = [NSTimeZone defaultTimeZone];
[[UIApplication sharedApplication]presentLocalNotificationNow:localNotification];
}
I would really appreciate some guidance to making my timer work in the background (just like Apple's timer). I'm not sure how I would use NSDateComponents since I also need the testTask.timeInterval to be updated even when the application in the background..
UIBackgroundTaskIdentifier bgTask =0;
UIApplication *app = [UIApplication sharedApplication];
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerCountDown:)
userInfo:nil
repeats:YES];
Now use this method to fire your notification. The timer will run in background.
As Josh Caswell wrote, you should save your timer state before your app goes in the background and then retrieve it when your app comes in the foreground again.
If you need to send a local notification at the right moment you can set it this way before entering the background, using your timer's state:
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMddHHmmss"];
NSDate *when = [dateFormat dateFromString:desiredTime];
// desiredTime -> time you want your local notification to be fired, take this from your timer before app enters the background
[dateFormat release];
localNotification.fireDate = when;
localNotification.timeZone = [NSTimeZone defaultTimeZone];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.alertBody = #"Hey";
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
[localNotification release];
EDIT: In your appDelegate you should find these methods:
(1) - (void)applicationWillResignActive:(UIApplication *)application
(2) - (void)applicationDidEnterBackground:(UIApplication *)application
(3) - (void)applicationWillEnterForeground:(UIApplication *)application
(4) - (void)applicationDidBecomeActive:(UIApplication *)application
(5) - (void)applicationWillTerminate:(UIApplication *)application
These are implemented specifically to manage the behavior of your app when its state changes.
There you can do everything needed before entering the background and when resumed.
Before entering the background you have some seconds to perform local notification schedule and save your timer state (using for example NSUserDefaults).
After that Apple will probably kill your app, if it doesn't try to work in the background for one of these reasons:
Implementing Long-Running Background Tasks For tasks that require more
execution time to implement,you must request specific permissions to
run them in the background without their being suspended. In iOS, only
specific app types are allowed to run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that keep users informed of their location at all times, such as a navigation app
Apps that support Voice over Internet Protocol (VoIP)
Newsstand apps that need to download and process new content
Apps that receive regular updates from external accessories
Taken from here.
I suggest you read this, about background tasks.

how to keep running NSTimer when app goes in background

I am creating puzzle game application and in that I am displaying time (i.e 01:20) using NSTimer. NSTimer is paused when application gone in background but i want to continue it even application is in background state.
for example timer count is 15 sec when app gone in background and I put it for 5 sec and become in foreground now I need to timer count changes to 20 sec
I have searched a lot but didn't get good answer.
So Please suggest me how can I achieve this.
Don't think of a timer as an object for timing something. Think of it rather as an object that pulses at a given frequency. To measure time, record a start time and compare it to the current time.
To record the start time, write it to a file as follows, probably in appWillResignActive:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:#"saveme.dat"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self.startDate];
[data writeToFile:filename atomically:NO];
// invalidate timer
When appWillBecomeActive:
NSData *data = [NSData dataWithContentsOfFile:filename]; // using the same code as before
self.startDate = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// start a timer for the purpose of pulsing only
Elapsed time at this point is:
NSDate *now = [NSDate date];
NSTimeInterval = [now timeIntervalSinceDate:self.startDate];
All of the foregoing can be done without running in the background. If you really need a timer to fire in the background, see this apple ref. Under "Background Execution". In a nutshell, you can do it, but Apple will make you meet several criteria before approving the app -- like it must be finite and provide utility for the user.
Create a NSDate ivar in your class to manage the starting time.
#implementation SomeClass {
NSDate *startTime;
}
For your timer, simply calculate the time through math on this date. Your timer is more used to invoke the method that does this calculation rather than determine the time itself...
[NSTimer scheduledTimerWithTimeInterval:0.1f target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
Logic for your method...
- (void)updateTimer {
if (!startTime) {
startTime = [NSDate date];
}
NSInteger secondsSinceStart = -(NSInteger)[startTime timeIntervalSinceNow];
NSLog(#"%d", secondsSinceStart);
}
You're going to need to write that information out to a file or cache the time at exit. Then when the application resumes you read that value in, do some math, and restart your timer.
In your AppDelegate as the app is going to background save the time to a file or NSUserDefaults. You can call NSDate's class method to get an Integer value you can easily store.
+ (NSTimeInterval)timeIntervalSinceReferenceDate
At application resume, read in the value. Get the current timeIntervalSinceReferenceDate and subtract. You should have the number of seconds that have elapsed.
I would recommend saving the start time as an NSDate object, and then having an NSTimer that, every second while the app is running, updates the displayed time by calculating the time interval between the current time and the start time. Pause the timer when your app goes into the background (so that you don't get a lot of unnecessary fires when your app starts back up) and restart it whenever the app enters the foreground.
If you want the data to be preserved across the app shutting completely (by being left in the background for too long, or closed in the app switcher) then you'll need to save data to disk at appropriate times.
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(showTime)
userInfo:NULL
repeats:YES];
- (void)showTime
{
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"HH:mm:ss"];
timeLabel.text=[dateFormatter stringFromDate:now];
}
Hope this answer will help you....

CoreLocation app working in Simulator but not on device

I am trying to run this program on iPhone 3GS with iOS 5. Program works fine on simulator but doesn't work on device. No error but the locationManager:didUpdateToLocation:fromLocation: delegate method doesn't get called when run on the device.
I just want to print location after every 30 seconds.
int main(int argc, char *argv[])
{
#autoreleasepool
{
iLocation *loc = [[iLocation alloc] init];
[loc start];
NSLog(#"In main");
}
return 0;
}
#interface iLocation : NSObject <CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
-(void) start;
-(void) startAgain;
#end
#import "BIDAppDelegate.h"
#implementation iLocation
#synthesize locationManager;
-(void) start
{
NSLog(#"Enter in start");
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
if([CLLocationManager locationServicesEnabled])
{
NSLog(#"Location Services are enabled");
[locationManager startUpdatingLocation];
}
else
NSLog(#"Location Services are disabled");
NSLog(#"Exit from start");
}
-(void) startAgain
{
[locationManager startUpdatingLocation];
}
- (void)locationManager: (CLLocationManager *)manager
didUpdateToLocation: (CLLocation *)newLocation
fromLocation: (CLLocation *)oldLocation
{
NSLog(#"Enter in didUpdateToLocation");
NSString *latitudeString = [NSString stringWithFormat:#"%g\u00B0",
newLocation.coordinate.latitude];
NSLog(#"Latitude = %#", latitudeString);
NSString *longitudeString = [NSString stringWithFormat:#"%g\u00B0",
newLocation.coordinate.longitude];
NSLog(#"Longitude = %#", longitudeString);
NSString *horizontalAccuracyString = [NSString stringWithFormat:#"%gm",
newLocation.horizontalAccuracy];
NSLog(#"Horizontal Accuracy = %#", horizontalAccuracyString);
NSString *altitudeString = [NSString stringWithFormat:#"%gm",
newLocation.altitude];
NSLog(#"Altitude = %#", altitudeString);
NSString *verticalAccuracyString = [NSString stringWithFormat:#"%gm",
newLocation.verticalAccuracy];
NSLog(#"Vertical Accuracy = %#", verticalAccuracyString);
NSTimer *timer = [NSTimer timerWithTimeInterval:20.0
target:self
selector:#selector(startAgain)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer
forMode:NSDefaultRunLoopMode];
NSLog(#"Exit from didUpdateToLocation");
}
your Location service may be off in iPhone please on it and try again.
in iPhone->setting->Location Service set it ON.
NSDate *now = [[NSDate alloc] init];
i think u have not initialized the date for today's date. And are u sure wether an app without a window or view, will be loaded into device..?
I think there's a couple potential problems with the code posted.
First of all, I just commented about this on another question. You don't need to keep telling CLLocationManager to startUpdatingLocation. You can just make that call once, until you decide to tell it to stopUpdatingLocation. Every time it gives you the new location, via
locationManager:didUpdateToLocation:fromLocation
you save/use it. You can have a timer fire every 30 seconds if you like, and if you don't have a newer location, then use the one from the last 30 seconds. Or use locationManager.location to get the most recent location fix.
See Apple's docs on CLLocationManager's startUpdatingLocation:
Calling this method several times in succession does not automatically
result in new events being generated. Calling stopUpdatingLocation in
between, however, does cause a new initial event to be sent the next
time you call this method.
Secondly, from the NSLog output you show above, and your main program, it looks like your program is just exiting before the location manager can ever deliver any location data. I have a non-graphical jailbreak app that has a process that runs and uses CoreLocation, and my main program looks like this:
#import "LocationDaemon.h"
int main(int argc, char *argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
LocationDaemon* daemon = [[LocationDaemon alloc] init];
// start a timer so that the process does not exit.
NSTimer* timer = [[NSTimer alloc] initWithFireDate: [NSDate date]
interval: 1.0
target: daemon
selector: #selector(run:)
userInfo: nil
repeats: NO];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer: timer forMode: NSDefaultRunLoopMode];
[runLoop run];
[daemon release];
[pool release];
[timer release];
return 0;
}
It looks to me like you don't add your timer until after you receive location data, which you never get to before the program exits. Try doing like I do above, and adding your timer earlier. I also call [runLoop run], after adding my timer. I think you have to do that, to keep your main thread looping. Your main program just calls start, which calls startUpdatingLocation, but those calls are not blocking. Fairly quickly, it gets done with that, and the program completes. I don't think having a retained CLLocationManager instance is enough to keep the program running.
I have no idea why it would work in the simulator, though :(
P.S. Don't be concerned that my timer defined above does not repeat. In the run: implementation, I believe it fires off another timer with a different interval, or selector. So, my program does in fact keep running.

How do I present an alarm to a user, even when my application is inactive?

I want to make an app which will let you set an alarm inside my iPhone app, then have it be activated even though my app is not running.
How would I implement this?
You want to use UILocalNotification. A couple things to note before you dive in:
It's only available on iOS4 and up.
NSDate is a pain in the ass, and it's the only option for scheduling
With that said, you can begin:
UILocalNotification *notif = [[UILocalNotification alloc] init];
notif.alertBody = #"This is a Local Notification";
NSDate *date = [NSDate date];
notif.fireDate = [date addTimeInterval:600];// fire the notification in ten minutes
[[UIApplication sharedApplication] scheduleLocalNotification:notif];
[notif release];
If you need any more help, just comment :)
try this:
in .h
int *currentTime;
in .m
-(void)startTimer {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateCurrentTime) userInfo:nil repeats:YES];
}
-(void)updateCurrentTime {
currentTime ++;
if (currentTime == userDefinedTime) {
// Time is up
}
}

iPhone: How to play a sound at a particular time?

I have written the following code:
-(void)runTimer
{
myTicker=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(showActivity) userInfo:nil repeats:YES];
myTicker = [NSTimer scheduledTimerWithTimeInterval:60.00 target:self selector:#selector(vibrate) userInfo:nil repeats:YES];
}
-(void)showActivity
{
NSDateFormatter *formatter =
[[[NSDateFormatter alloc] init] autorelease];
NSDate *date = [NSDate date];
[formatter setTimeStyle:NSDateFormatterMediumStyle];
[timerLabel setText:[formatter stringFromDate:date]];
}
-(void) vibrate{
AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}
I want to play an audio file instead of vibrating the iPhone. Is that possible?
Tangential to the main question but the method called by the timer selector should be of the form...
-(void) aribtaryMethodName:(NSTimer *) theTimer;
...or it may not be called properly. It's selector should look like this:
myTicker=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(aribtaryMethodName:) userInfo:nil repeats:YES];
Check Apple's sample project BubbleLevel. You want the SoundEffect.h and SoundEffect.m into your project and then just call:
mySound = [[SoundEffect alloc]
initWithContentsOfFile:[mainBundle pathForResource:#"mySound"
ofType:#"aif"]];
[mySound play];
Warning: I was able to play only AIF sounds converted via iTunes. Anything else failed, including CAF files. In short: import your whatever sound into iTunes (drag'n'drop), change export to AIF format and then export the file.
Yes. Assume you have a .caf file, you can play it with
SystemSoundID sound_id;
AudioServicesCreateSystemSoundID(NSURL_of_your_caf_file, &sound_id);
...
AudioServicesPlaySystemSound(sound_id);
To play music you may want to use AVAudioPlayer instead.
Sure. See AVAudioPlayer class.
-(IBAction)slider1Changed:(id)sender
{
[timer invalidate];
float sliderValue=slider1.value;
int totalSecond=(int)sliderValue;
time=totalSecond;
int sec= totalSecond %60;
int min= (totalSecond -sec)/60;
sliderValue=(float)totalSecond;
runTime.text=[NSString stringWithFormat:#"%d:%.2d",min,sec];
[slider1 setValue:sliderValue];
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerChanged) userInfo:nil repeats:YES];
// to play the audio from particular time duration
[player setCurrentTime:totalSecond];
}
-(void)timerChanged
{
int totalSecond=[player duration];
float slider1Time=(float)time;
if (time <= totalSecond) {
int sec= time %60;
int min= (time -sec)/60;
runTime.text=[NSString stringWithFormat:#"%d:%.2d",min,sec];
[slider1 setValue:slider1Time];
}
else
{
[player stop];
[timer invalidate];
}
time +=1;
}