How can i call NStimer form one viewcontroller from unother viewcontroller? - iphone

At first time i call the timer like this in Third viewcontroller
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:NO];
Then timer called the targetMethod
-(void)targetMethod
{
First * sVC = [[First alloc] initWithNibName:#"First" bundle:[NSBundle mainBundle]];
[self presentModalViewController:sVC animated:YES];
[sVC release];
[timer invalidate];
}
First viewcontroller opened..
In First viewcontroller had one button.In button action
i wrote
- (IBAction) Action:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
Third *BVC=[[Third alloc]init];
[Bvc TimerStart]; //Timestart is function i start timer in this function..
//i want to call Third viewcontroller timer function this place
}
timer started..But view didn't open (first )viewcontroller.......
Please help me......

Bala,
Place the NSTimer object in the App Delegate .h file, include that .h file in wherever you use the timer. This will allow the NSTimer to be a global timer which you can call from any other view that includes the app delegate header file.
In app delegate .h file (in the appropriate areas):
NSTimer *delayTimer;
#property (nonatomic, retain) NSTimer *delayTimer;
Synthesize this in the app delegate .m file (remember to release it in dealloc):
#synthesize delayTimer;
Then in whichever views you use the timer in, access it like this:
// get global variable
SomeNameHereAppDelegate *mainDelegate = (SomeNameHereAppDelegate *)[[UIApplication sharedApplication] delegate];
mainDelegate.delayTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(targetMethod) userInfo:nil repeats:NO];
Then when you want to invalidate it from somewhere, you just do this:
[mainDelegate.delayTimer invalidate];
mainDelegate.delayTimer = nil;

What if if i need to have a count down timer which should be shared among the view controllers.do i have to make it in the app delegate where the remaining seconds could be an ivar also in app delegate with property?
In this case i would post notification from the timer handler after updating the remaining seconds

In AppDelegate.h
#property int timePassed;
In AppDelegate.m
#synthesize timePassed;
In ViewController.h
#property (weak, nonatomic)NSTimer *timer;
#property (weak, nonatomic) IBOutlet UILabel *time;
In ViewController.m
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
delegate.timePassed = 180;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(TimePasses) userInfo:nil repeats:YES];;
}
-(void) TimePasses{
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
delegate.timePassed = delegate.timePassed - 1;
NSLog(#"TimePasses %d", delegate.timePassed);
int minuts = delegate.timePassed / 60;
int seconds = delegate.timePassed - (minuts * 60);
NSString *timerOutput = [NSString stringWithFormat:#"%2d:%.2d", minuts, seconds];
time.text = timerOutput;
}
In SecondViewController.h
#property (weak, nonatomic)NSTimer *timer;
#property (weak, nonatomic) IBOutlet UILabel *time;
In SecondViewController.m
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(TimePasses) userInfo:nil repeats:YES];;
}
-(void) TimePasses{
AppDelegate *delegate = (AppDelegate*) [[UIApplication sharedApplication] delegate];
NSLog(#"TimePasses in 2 %d", delegate.timePassed);
int minuts = delegate.timePassed / 60;
int seconds = delegate.timePassed - (minuts * 60);
NSString *timerOutput = [NSString stringWithFormat:#"%2d:%.2d", minuts, seconds];
time.text = timerOutput;
}

Related

Change NSTime with respect to the value of UISlider

There are lots of questions and answers about how to change the UISlider value with NsTimer but i need to create the reverse condition i need to change the NSTimer interval per UISlider value change, and want the slider value work in reverse manner. so can anyone help to achieve this?
Thanks for your approaches and time :)
you can set Timer set again interval value at the IBAction of UISlier Method like:-
.h class:-
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UILabel *lblTimer;
IBOutlet UISlider *timeSlider;
}
#property(nonatomic,strong)NSTimer *timer;
.m class:-
- (void)viewDidLoad
{
[super viewDidLoad];
_timer=[[NSTimer alloc]init];
_timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateLable) userInfo:nil repeats:YES];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
int i=0;
-(IBAction)changeSlider:(UISlider*)sender
{
NSLog(#"%d",(int)sender.value);
[_timer invalidate];
_timer=[[NSTimer alloc]init];
_timer=nil;
_timer = [NSTimer scheduledTimerWithTimeInterval:(int)sender.value target:self selector:#selector(updateLable) userInfo:nil repeats:YES];
// i=0;
//text_field .text= [[NSString alloc] initWithFormat:#" Value %d ", (int)slider.value];
}
-(void)updateLable
{
[lblTimer setText:[NSString stringWithFormat:#"%d",i]];
i++;
}
OUTPUT OF CODE

updating UILabel from appDelegate

I have been having this issue from last couple of hours and did all the search that i could but unfortunately, i didnt find anything that resolves my issue....
Scenario: i have a CountDownTimer in TimerViewController, NSTimer and other methods are set up in AppDelegate which is suppose to update TimerViewController's Label... as per label's setter, i'm getting the value correctly and its showing in the NSLog HOWEVER, the label is not updating on the screen... this setter is being called from AppDelegate every second and the Label is suppose to show the Timer,
- (void)setMainTimerLabel:(UILabel *)mainTimerLabel
{
_mainTimerLabel = mainTimerLabel;
NSLog(#"ValueUpdated %#",_mainTimerLabel);
}
I have double checked the label, it hooked up with interface correctly, i tried to update the label from ViewDidLoad with test String, the label was showing me the string...
Help please!
EDIT:
AppDelegate Code:
AppDelegate.h
#property (nonatomic, strong) TimerViewController *TimerVC;
- (void)fireTimer;
AppDelegate.m
- (void)fireTimer
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDownTimer) userInfo:nil repeats:YES];
}
- (void) countDownTimer
{
.......
TimerVC = [[TimerViewController alloc]init];
self.TimerVC.mainTimerLabel = [NSString stringWithFormat:#"%02d:%02d:%02d",hours,minutes,seconds];
.......
}
I resolved this issue following the below code by jabobadilla
I actually solved it by performing a method that will go and retrieve the value that the NSTimer is updating in my AppDelegate, since the method firing the NSTimer is no longer in the main thread when I leave the view and come back to it. This method will loop as long as my NSTimer is valid. I also placed a delay, allowing for the UI to update the value, and then perform the method again. Here is the code in case it helps someone running into a similar issue. I got this idea from the suggestion provided by chandan, thanks!!
AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate> {
}
#property (nonatomic, retain) NSTimer *countdownTimer;
#property (nonatomic, retain) NSString *timeString;
CountdownTimerViewController.h
#interface CountdownTimerViewController : UIViewController {
AppDelegate *appdelegate;
}
#property (strong, nonatomic) IBOutlet UILabel *labelCountdownTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStartTimer;
#property (strong, nonatomic) IBOutlet UIButton *buttonStopTimer;
- (IBAction)startTimer:(id)sender;
- (IBAction)stopTimer:(id)sender;
CountdownTimerViewController.m
#implementation CountdownTimerViewController
#synthesize labelCountdownTimer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Instatiating Appdelegate
if(!appdelegate)
appdelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (void) viewDidAppear:(BOOL)animated {
if ([appdelegate.countdownTimer isValid]) {
[self updateLabel];
} else {
labelCountdownTimer.text = #"00:00:00";
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Button Action Methods
- (IBAction)startTimer:(id)sender {
[self updateCounter];
}
- (IBAction)stopTimer:(id)sender {
[appdelegate.countdownTimer invalidate];
labelCountdownTimer.text = #"00:00:00";
}
int countLimit=30; //seconds
NSDate *startDate;
- (void)updateCounter {
labelCountdownTimer.text = #"00:00:00";
startDate = [NSDate date];
appdelegate.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(countDown)
userInfo:nil
repeats:YES];
}
- (void)countDown {
if([[NSDate date] timeIntervalSinceDate:startDate] >= countLimit) {
[appdelegate.countdownTimer invalidate];
return;
}
else {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = -([currentDate timeIntervalSinceDate:startDate]);
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
appdelegate.timeString = [dateFormatter stringFromDate:timerDate];
labelCountdownTimer.text = appdelegate.timeString;
}
}
- (void) updateLabel {
if ([appdelegate.countdownTimer isValid]) {
labelCountdownTimer.text = appdelegate.timeString;
[self performSelector:#selector(updateLabel) withObject:nil afterDelay:0.05];
}
}
There may be problem in your IBOutlet....
Try to create a programatic UILabel and pass the _mainTimerLabel value to that label....
This may help you..

start and stop timer of one view from another view

in my app there are two views. view1 has a function testing
-(void) testing
{
NSLog(#"Testing : %d", (++x));
}
and a timer
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(testing) userInfo:nil repeats:YES];
what i want, is to stop and run this timer from view2. How to do that ?
Define Timer in AppDelegate,
#interface TimerDemoAppDelegate : NSObject <UIApplicationDelegate>
{
NSTimer *timer;
}
#property (nonatomic, retain) NSTimer *timer;
#end
And use timer in your both view by creating TimerDemoAppDelegate object
in your view .h file
#interface View1 : UIViewController
{
TimerDemoAppDelegate *appDelegate;
}
in your view .m file
appDelegate=(TimerDemoAppDelegate *)[[UIApplication sharedApplication] delegate];
now use timer as appDelegate.timer.
Add timer2 to your View2 class
#interface View2 : UIView{
NSTimer *timer2;
}
#property (nonatomic,retain) NSTimer *timer2;
#end
#implementation View2
#synthesize timer2;
#end
and do like this
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(testing) userInfo:nil repeats:YES];
view2.timer2 = timer;
Using NSNotificationCenter you can call methods from another view without creating any objects.
In your viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(button:)
name:#"Next"
object:nil];
-(void)button:(NSNotification *) notification
{
// write a code of timer here.....
}
//call this following from another view
[[NSNotificationCenter defaultCenter]
postNotificationName:#"Next"
object:self];
Enjoy with this code....

Problem with NSTimer

Edit2: Why only progress got updated in "doSomething" method but not point0?
Edit: with the code I have. I know I must overlook something, but I just could not find it.
I am writing an iphone app which uses NSTimer to do some tasks. In the program, I could not get the updated value of the variable updated inside NSTimer loop. Here is my code.
Interface File
import
#interface TestNSTimerViewController : UIViewController {
IBOutlet UIProgressView *progress;
IBOutlet UIButton *button;
IBOutlet UILabel *lable1;
IBOutlet UILabel *lable2;
NSTimer *timer;
float point0;
}
#property (nonatomic, retain) UIProgressView *progress;
#property (nonatomic, retain) UIButton *button;
#property (nonatomic, retain) NSTimer *timer;
#property (nonatomic, retain) UILabel *lable1;
#property (nonatomic, retain) UILabel *lable2;
- (IBAction)buttonClicked:(id)sender;
#end
Implementation file
#import "TestNSTimerViewController.h"
#implementation TestNSTimerViewController
#synthesize progress;
#synthesize button;
#synthesize lable1;
#synthesize lable2;
#synthesize timer;
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)buttonClicked:(id)sender {
point0 = 1.0f;
lable1.text = [NSString stringWithFormat:#"%3.1f",point0];
timer = [NSTimer scheduledTimerWithTimeInterval:0.05
target:self selector:#selector(doSomething) userInfo:nil repeats:YES];
lable2.text = [NSString stringWithFormat:#"%3.1f",point0];
}
- (void)doSomething {
progress.progress = progress.progress+0.1;
point0 = 2.0f;
if (progress.progress == 1.0) {
[timer invalidate];
}
}
- (void)dealloc {
[button release];
[progress release];
[lable1 release];
[lable2 release];
[timer release];
[super dealloc];
}
#end
After the NSTimer loop, I checked the value of point0. It did not change the value to 2.3. What's wrong with the code?
Thank you,
From the Reference document
Once scheduled on a run loop, the timer fires at the specified interval until it is invalidated. A non-repeating timer invalidates itself immediately after it fires. However, for a repeating timer, you must invalidate the timer object yourself by calling its invalidate method. Calling this method requests the removal of the timer from the current run loop; as a result, you should always call the invalidate method from the same thread on which the timer was installed. Invalidating the timer immediately disables it so that it no longer affects the run loop. The run loop then removes and releases the timer, either just before the invalidate method returns or at some later point. Once invalidated, timer objects cannot be reused.
The timer you use is a Repeating timer, so you should not invalidate it at all. Or use the following Line, because the timer needs to fired each time the button is clicked. I have set the repeat parameter to NO.
timer = [NSTimer scheduledTimerWithTimeInterval:0.05
target:self selector:#selector(doSomething) userInfo:nil repeats:NO];
- (void)buttonClicked:(id)sender {
point0 = 1.0f;
lable1.text = [NSString stringWithFormat:#"%3.1f",point0];
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05
target:self selector:#selector(doSomething) userInfo:nil repeats:NO];
lable2.text = [NSString stringWithFormat:#"%3.1f",point0];
}
Then in doSometing function:
- (void)doSomething {
progress.progress = progress.progress+0.1;
point0 = 2.0f;
if (progress.progress < 1.0) {
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.05
target:self selector:#selector(doSomething) userInfo:nil repeats:NO];
}
}
I think you should reset the progress variable at some point.
I found the answer. label2.text line is executed before NSTimer finishes the run loop. I need to rewrite my code such that it waits until NSTimer finishes the run loop.

iphone NSMutableArray loses objects at end of method

in my app, an NSMutableArray is populated with an object in viewDidLoad (eventually there will be many objects but I'm just doing one til I get it working right). I also start a timer that starts a method that needs to access the NSMutableArray every few seconds. The NSMutableArray works fine in viewDidLoad, but as soon as that method is finished, it loses the object.
myApp.h
#interface MyApp : UIViewController {
NSMutableArray *myMutableArray;
NSTimer *timer;
}
#property (nonatomic, retain) NSMutableArray *myMutableArray;
#property (nonatomic, retain) NSTimer *timer;
#end
myApp.m
#import "MyApp.h"
#implementation MyApp
#synthesize myMutableArray;
- (void) viewDidLoad {
cycleTimer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:#selector(newCycle) userInfo: nil repeats:YES];
MyObject *myCustomUIViewObject = [[MyObject alloc]init];
[myMutableArray addObject:myCustomUIViewObject];
[myCustomUIViewObject release];
NSLog(#"%i",[myMutableArray count]); /////outputs "1"
}
-(void) newCycle {
NSLog(#"%i",[myMutableArray count]); /////outputs "0" ?? why is this??
}
myApp.m is not retaining the array unless you assign to it using self.myMutableArray, unless you use the self. prefix you do not get the benefit of the (nonatomic, retain).
Your results point to an array that is not allocated at the time you read from it. It's either this or failing to allocate the array before using addObject (unlikely given your NSLog result).
- (void) viewDidLoad {
self.myMutableArray = [NSMutableArray array];
...
}
would probably fix this up.
Try this
- (void) viewDidLoad {
cycleTimer = [NSTimer scheduledTimerWithTimeInterval:4.0 target:self selector:#selector(newCycle) userInfo: nil repeats:YES];
MyObject *myCustomUIViewObject = [[MyObject alloc]init];
NSMutableArray *my_array = [[NSMutableArray alloc] initWithCapacity:3];
self.myMutableArray = my_array;
[my_array release];
[myMutableArray addObject:myCustomUIViewObject];
[myCustomUIViewObject release];
NSLog(#"%i",[myMutableArray count]); /////outputs "1"
}
and don't forget to
- (void) viewDidUnLoad {
self.myMutableArray = nil;
}
and
- (void) dealloc{
[myMutableArray release];
[super dealloc];
}