iOS can we reuse a NSTimer - ios

I want to use an NSTimer (or if you have a better suggestion) to play a sound when the device is unplugged, or unknown. However if the user plugs the device back in, the sound should immediately stop.
Here's my code but it doesn't seem to behave as I am describing it,
- (void)currentBatteryState
{
UIDevice *device = [UIDevice currentDevice];
switch(device.batteryState) {
case UIDeviceBatteryStateUnknown:
currentBatteryStatusLabel.text = #"Unknown";
if ([batteryControlTimer isValid]) {
[batteryControlTimer invalidate];
batteryControlTimer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(playSound) userInfo:nil repeats:YES];
} else {
batteryControlTimer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(playSound) userInfo:nil repeats:YES];
}
break;
case UIDeviceBatteryStateUnplugged:
currentBatteryStatusLabel.text = #"Unplugged";
if ([batteryControlTimer isValid]) {
[batteryControlTimer invalidate];
batteryControlTimer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(playSound) userInfo:nil repeats:YES];
} else {
batteryControlTimer = [NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(playSound) userInfo:nil repeats:YES];
}
break;
case UIDeviceBatteryStateCharging:
currentBatteryStatusLabel.text = #"Charging";
[batteryControlTimer invalidate];
break;
case UIDeviceBatteryStateFull:
currentBatteryStatusLabel.text = #"Full";
[batteryControlTimer invalidate];
break;
}
}
- (void) playSound
{
CFBundleRef mainBundle = CFBundleGetMainBundle();
CFURLRef soundFileURLRef;
soundFileURLRef = CFBundleCopyResourceURL(mainBundle, (CFStringRef) #"siren_1", CFSTR ("mp3"), NULL);
UInt32 soundID;
AudioServicesCreateSystemSoundID(soundFileURLRef, &soundID);
AudioServicesPlaySystemSound(soundID);
}
Thank you

If the condition isn't met, don't play any sound, but don't invalidate the timer. That way it will keep firing at the interval even if the condition isn't met once.
So:
- (void)playSound {
if(conditionIsMet) {
//code to play your sound
}
}
Edit:
If you want to make the interval at which the sound can stop because the condition isn't met, then you just need to make the timer's time interval and the duration of the sound smaller.

Related

UIProgressView not updating for Audio Player?

The ProgressView is not updating while playing the song. By reading from other post i have used an update method to update at each time interval.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"Fix you_Coldplay" ofType:#"mp3" inDirectory:#"Coldplay"];
NSLog(#"%#",filePath);
NSURL *url = [NSURL fileURLWithPath:filePath];
NSLog(#"%#",url);
musicPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
[musicPlayer prepareToPlay];
[trackProgress setProgress:0.0];
}
I have a play button which is also being used for calling updateTime: method.
- (IBAction)playButton:(id)sender {
[musicPlayer play];
[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
NSTimeInterval interval = musicPlayer.currentTime/musicPlayer.duration;
NSLog(#"%f",interval);
}
The updateTime: method
-(void)updateTime:(NSTimer *)timer {
trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
}
I am very new to programming and even stack overflow. This is the first question i am posting. Please help me and Thanks in advance.
First of all change timer value to:
//Change Value to 0.5 or 1 sec
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
Make sure you are setting trackProgress as 0 as initial value.
- (void)viewDidLoad {
[super viewDidLoad];
trackProgress.progress = 0.0;
}
Hope this will resolve your issue.
Make sure to update the progress view on the main thread
-(void)updateTime:(NSTimer *)timer {
dispatch_async(dispatch_get_main_queue(), ^{
self.trackProgress.progress = (musicPlayer.currentTime/musicPlayer.duration);
});
}
This might help. Create a Timer and add it to common runloop as shown below. Also keep a reference to timer so that it can be stopped later.
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

how to resume time counter value in when i start the app

I want to resume time counter value in when I start the app.like first my label value is 05:00 than after close the app but when I start the app agin that time timer count start to 05:00. Please help me
int timeSec,timeMin ;
- (void)viewDidLoad {
timeSec=0;
timeMin=0;
[self StartTimer];
}
-(void) StartTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerTick:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
}
//Event called every time the NSTimer ticks.
- (void)timerTick:(NSTimer *)timer
{
timeSec++;
if (timeSec == 60)
{
timeSec = 0;
timeMin++;
}
//Format the string 00:00
NSString* timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
//Display on your label
//[timeLabel setStringValue:timeNow];
self.lbl_timer.text= timeNow;
}
//Call this to stop the timer event(could use as a 'Pause' or 'Reset')
- (void) StopTimer
{
// [timer invalidate];
timeSec = 0;
timeMin = 0;
//Since we reset here, and timerTick won't update your label again, we need to refresh it again.
//Format the string in 00:00
NSString* timeNow = [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];
//Display on your label
// [timeLabel setStringValue:timeNow];
self.lbl_timer.text= timeNow;
}
thanks for advance..
Try this code.store data in nsuserdefault
- (void)viewDidLoad {
timeSec=[[NSString stringWithFormat:#"%ld",(long)[[NSUserDefaults standardUserDefaults]integerForKey:#"timeSec"]] intValue];
timeMin=[[NSString stringWithFormat:#"%ld",(long)[[NSUserDefaults standardUserDefaults]integerForKey:#"timeMin"]] intValue];
[self StartTimer];
}
-(void) StartTimer
{
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerTick:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
self.lbl_timer.text=#"00:00";
}
- (void)timerTick:(NSTimer *)timer
{
timeSec++;
if (timeSec == 60)
{
[locationManager startUpdatingLocation];
timeSec = 0;
timeMin++;
}
self.lbl_timer.text= [NSString stringWithFormat:#"%02d:%02d", timeMin, timeSec];;
}
when you back to the screen that time add this code.like back button or close button action
[timer invalidate];
[[NSUserDefaults standardUserDefaults]setInteger:timeSec forKey:#"timeSec"];
[[NSUserDefaults standardUserDefaults]setInteger:timeMin forKey:#"timeMin"];
Declare two variable in appdelegate file
1)NSUserDefaults *usedefaults;
2)#property (nonatomic,readwrite) int timeSec,timeMin,isBackground;
- (void)applicationDidEnterBackground:(UIApplication *)application
{
self.isBackground=1;
usedefaults=[NSUserDefaults standardUserDefaults];
[usedefaults setObject:[NSString stringWithFormat:#"%d",self.timeMin] forKey:#"timemin"];
[usedefaults setObject:[NSString stringWithFormat:#"%d",self.timeSec] forKey:#"timesec"];
NSLog(#"Enter in back value userdefault %#",usedefaults);
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
if(self.isBackground==1)
{
self.isBackground=0;
self.timeMin=[[usedefaults objectForKey:#"timemin"] intValue];
self.timeSec=[[usedefaults objectForKey:#"timesec"] intValue];
NSLog(#"Foreground value min %d sec %d",self.timeMin,self.timeSec);
}
}
In ViewDidload in your Timer startpage
app=(AppDelegate *)[[UIApplication sharedApplication] delegate];
finally just replace you self.timemin to app.timemin same for timesec.
Cheers enjoy That surely work for u ..

Managing Timers Passed as Variables

I am trying to perform what I thought was a simple task. I have a handful of repeating timers that need to be started and stopped.
I created methods for starting and stopping the timers, and attempt to pass the timers to the methods as parameters.
The problem is that the timers never seem to be stopped. Any ideas why this might not be working properly? Thank you!
Top of File:
#import "ViewController.h"
NSTimer *launchTimer;
NSTimer *transactionTimer;
Starting Method:
-(void) startingMethod {
NSString *urlString = #"http://google.com";
[[AsynchRequestService sharedInstance]
performAsynchronousURLRequest:urlString completion:^(BOOL success,
NSString *responseBody, NSString *responseStatus) {
if (success) {
[self stopResponseTimer:launchTimer];
}
else {
[self startResponseTimer:launchTimer
method:#selector(startingMethod)
interval:10];
}
}];
}
Method to Start the Timer:
-(void)startResponseTimer:(NSTimer *) timer method:(SEL) method
interval:(int) interval {
[timer invalidate];
timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self
selector:method userInfo:nil repeats:YES];
}
Method to Stop the Timer:
-(void)stopResponseTimer:(NSTimer *) timer {
NSLog(#"STOP TIMER");
[timer invalidate];
timer = nil;
}
Make startResponseTimer and `stopResponseTimer' take the pointer to the object pointer intead.
-(void)startResponseTimer:(NSTimer **) timer method:(SEL) method
interval:(int) interval {
[*timer invalidate];
*timer = nil;
*timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self
selector:method userInfo:nil repeats:YES];
}
-(void)stopResponseTimer:(NSTimer **) timer {
NSLog(#"STOP TIMER");
[*timer invalidate];
*timer = nil;
}
then invoke it like
[self startResponseTimer:&launchTimer];
[self stopResponseTimer:&launchTimer];
This should make sure that you retain the right NSTimer object.
NOTE:It is always a good idea to check a pointer to a pointer to an object for NULL in a public method

Need fading effect while playing music

In my application, I'm using both iPod Player for playing background music(Music App) and AvAudioPlayer for playing the songs from URL's. I want to put fading effect for the songs while switching between these players. I tried the way by decreasing the volume of one player and increasing the other, but it did not give me the fading effect. Can anyone help me how to achieve this?
Thanks in advance
This is my code
- (IBAction)play:(id)sender
{
timerCount = 0;
playAndPauseTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(playTimer) userInfo:nil repeats:YES];
}
-(void)playTimer
{
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
if(timerCount < 10) {
timerCount++;
float volume = musicPlayer.volume;
if(volume>0) {
volume = musicPlayer.volume-0.02f;
[musicPlayer setVolume:volume];
}
} else {
[playAndPauseTimer invalidate];
[musicPlayer setVolume:initialVolume];
[audioplayer play];
pauseButton.hidden = NO;
startButton.hidden = YES;
}
}
- (IBAction)pause:(id)sender
{
//[self pauseTimer];
timerCount=0;
playAndPauseTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(pauseTimer) userInfo:nil repeats:YES];
}
-(void)pauseTimer
{
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController iPodMusicPlayer];
if(timerCount < 10) {
timerCount++;
float volume = musicPlayer.volume;
if(volume > 0){
volume = musicPlayer.volume-0.02f;
[musicPlayer setVolume:volume];
}
} else {
[playAndPauseTimer invalidate];
[audioplayer pause];
[musicPlayer setVolume:initialVolume];
pauseButton.hidden = YES;
startButton.hidden = NO;
}
}

how to make NSTimer consistent on xcode

I'm making a game and would like to use a timer to countdown an event, just like what's seen on Bejeweled. I know that I've to put NSTimer in a NSRunLoop to make it work, since NSTimer is inaccurate. Have tried the following but it still don't work. Please help!
#import ...
NSTimer *_gameTimer;
int secondsLeft;
//some code
//called countdownTimer using [self countdownTimer];
- (void)countdownTimer
{
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
NSRunLoop *gameRun = [NSRunLoop currentRunLoop];
[gameRun addTimer:_gameTimer forMode:NSDefaultRunLoopMode];
}
- (void)updateTime:(NSTimer *)timer
{
if (secondsLeft>0 && !_gameOver) {
_timerLabel.text = [NSString stringWithFormat:#"Time left: %ds", secondsLeft];
secondsLeft--;
} else if (secondsLeft==0 && !_gameOver) {
// Invalidate timer
[timer invalidate];
[self timerExpire];
}
}
- (void)timerExpire
{
// Gameover
[self gameOver];
[_gameTimer invalidate];
_gameTimer = nil;
}
NSTimer needs to be a local variable so there can only be one instance of the object running through the loop. Here's the code.
- (void)countdownTimer
{
NSTimer *_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
NSRunLoop *gameRun = [NSRunLoop currentRunLoop];
[gameRun addTimer:_gameTimer forMode:NSDefaultRunLoopMode];
if (secondsLeft==0 || _gameOver) {
[_gameTimer invalidate];
_gameTimer = nil;
}
}
- (void)updateTime:(NSTimer *)timer
{
if (secondsLeft>0 && !_gameOver) {
_timerLabel.text = [NSString stringWithFormat:#"Time left: %ds", secondsLeft];
secondsLeft--;
} else if (secondsLeft==0 || _gameOver) {
// Invalidate timer
[timer invalidate];
[self timerExpire];
}
- (void)timerExpire
{
// Gameover
[self gameOver];
}

Resources