I am trying to create a framework for all of the custom objects and views that I have made and use often, by creating custom delegate classes and custom objects. Everything has gone well except when trying to get NSTimers to call the correct method inside of the delegate class.
Here is the basic setup.
-(void) startTimers {
NSTimer *timer1 = [NSTimer timerWithTimeInterval:5 target:self selector:#selector(doSomething:) userInfo:nil repeats:YES];
NSTimer *timer2 = [NSTimer timerWithTimeInterval:5 target:self selector:#selector(doSomethingElse:) userInfo:nil repeats:YES];
}
I can easily just call this method and whatever, but when this time fires it does not call the method I defined as the selector. I am pretty sure it has something to do with the delegate value and which class it is making as the delegate.
Note the file I am writing in is a subclass of UIView, which is set up to be a delegate using the #protocol tags and all of that.
What should I set as the target when defining my timers to get them to call the correct methods.
EDIT:
Here is an example of what I am doing:
ExampleView.h
#import <UIKit/UIKit.h>
#protocol ExampleViewDelegate;
#interface ExampleView : UIView {
NSTimer *timer;
}
-(void) initWithStuff:(id)stuff andFrame:(CGRect)frame;
-(void) testTimer;
#end
#protocol ExampleViewDelegate
-(void) someDelegateFunction;
#end
ExampleView.m
#import "ExampleView.h"
#implementation ExampleView
-(id) initWithStuff:(id)stuff andFrame:(CGRect)frame {
self = [super initWithFrame:frame];
timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:#selector(testTimer) userInfo:nil repeats:YES];
return self;
}
-(void) testTimer {
NSLog(#"Timer Fired");
}
#end
If you add this custom view into a viewcontroller it will never call that testTimer function and print "Timer Fired" So what I am thinking is that when I set the delegate for this timer, it is actually setting it to something else. Any ideas?
NSTimer *timer1 = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(doSomething:) userInfo:nil repeats:YES];
Notice the method is called "scheduledTimerWithTimeInterval"
Related
I'm trying to to stop an NSTimer with the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
timer3 = [NSTimer timerWithTimeInterval:5.0 target:self selector:#selector(start) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer3 forMode:NSDefaultRunLoopMode];
}
-(void)invalidate
{
[timer3 invalidate];
timer3 = nil;
}
and I call -(void)invalidate from another class like this:
-(void)timer
{
ClassOfMyTimer *class = [[ClassOfMyTimer alloc] init];
[class invalidate];
}
but the timer doesn't stop. Does anyone know what I'm doing wrong?
You need to call your invalidate method on the same instance of your class that created the timer. In your timer method you create a new instance of your class which could have its own timer and invalidate that.
I'm kind of confused by what you're trying to do here, but I'd guess that you're not maintaining a reference to timer3.
Have you created a property in the .h file for the timer:
#property (strong) NSTimer *timer3;
And then added a synthesize statement in the .m file:
#synthesize timer3;
Then, in viewDidLoad:, you can maintain a reference to the timer you're creating via:
self.timer3 = [[[NSTimer timerWithTimeInterval:5.0 target:self selector:#selector(start) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:self.timer3 forMode:NSDefaultRunLoopMode];
And, to invalidate the timer later:
[self.timer3 invalidate]
self.timer3 = nil
On preview, Sven also has a valid solution to an issue that might be impacting you..
Following is my sample code.
#interface TrackTimer : NSObject {
NSTimer *timer;
}
#property (nonatomic, retain) NSTimer *timer;
- (void) startTimer;
- (void) stopTimer;
- (void) timerFired;
#end
TrackTimer.m
#synthesize timer;
- (void) startTimer
{
NSLog(#"Timer started ...");
if(timer)
{
timer = nil;
}
timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:#selector(timerFired) userInfo:nil repeats:NO];
}
- (void) stopTimer
{
NSLog(#"Timer stoped ...");
[tTimer invalidate];
}
- (void) timerFired
{
NSLog(#"Timer Fired ... :)");
}
I have to use the same timer object from 3 different view controllers, my problem is startTimer method do not invoke timerFired method in 2nd UIViewController. Its works perfectly on 1st and 3rd View Controller.
appln Flow : 1stView -> 2ndView -> 3rdView
You are doing everything right... almost.
Your timer does not fire, because of the "if" statement.
if (timer) {
timer = [NSTimer scheduledTimerWithTimeInterval:5 target:self selector:#selector(boom) userInfo:nil repeats:NO];
}
Here, the "if" statement returns NO, because the timer is not yet initialized..
The fact that you make it a property and synthesize it does not mean that (timer != nil)
If you remove the "if" statement it should work...
From the Apple docs on NSTimer:
The message to send to target when the timer fires. The selector must have the following signature:
- (void)timerFireMethod:(NSTimer*)theTimer
So, it looks like the signature of your timerFired method needs to be expanded to include one parameter '(NSTimer*)theTimer' and your selector needs to be #selector(timerFired:)
Don't really know how you do that, but NStimer has a class method called
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats. So you can do it like this:
timer=[NSTimer scheduledTimerWithTimeInterval:2 target:self
selector:#selector(timerFired)
userInfo:nil
repeats:YES];
This will invoke the timerFired method for you.
P.S.Here's the link to a simple app that does just what you want.
http://www.mediafire.com/?8uz115drqzb2nan
This is probably something I should know by now, I am creating an instance of NSTimer using the NSTimer class method. I am pretty sure the returned object is autoreleased, my question is in terms of memory management should I be then retaining and releasing the timer object (METHOD: 1), or simply just assigning it directly to the #property (METHOD: 2)(or should I be doing something totally different?)
// METHOD: 1
#property (nonatomic, retain) NSTimer *myTimer;
.
NSTimer *tempTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(executeOnTimer) userInfo:nil repeats:YES];
[self setMyTimer:tempTimer];
//[tempTimer release];
.
- (void)dealloc {
[pulseTimer release];
[super dealloc];
}
OR SIMPLY:
// METHOD: 2
myTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(executeOnTimer) userInfo:nil repeats:YES];
EDIT:
One final point, if I just write (see below) without assigning to a property is there any chance that the timer is going to get deallocated, basically does it stay around until the program exits. Just curious how its retained?
[NSTimer scheduledTimerWithTimeInterval:120.0 target:self selector:#selector(executeOnTimer) userInfo:nil repeats:YES];
In order to take ownership over the NSTimer you can do one of these with the same effect:
self.myTimer = [NSTimer scheduledTimerWithTimeInterval: ...]; // implicit setter
or
[self setMyTimer: [NSTimer scheduledTimerWithTimeInterval:...]]; // explicit setter
or
myTimer = [[NSTimer scheduledTimerWithTimeInterval: ...] retain];
or
self->myTimer = [[NSTimer scheduledTimerWithTimeInterval: ...] retain];
This is the good way:
self.myTimer = tempTimer;
// don't call [tempTimer release]
This will retain it automcailcally due to the property which retains it.
Just calling myTimer = … doesn't use the setter while self.myTimer = … does.
how can i stop NSTimer in runTime?
I am using the following code .but NSTimer runs again and again.(i want to repeat NStimer, i want to stop in runtime )
- (void)TimerCallback
{
.....
[self.tim invalidate];
self.tim = nil;
}
-(void)timerStart
{
self.tim = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(TimerCallback) userInfo:nil repeats:YES];
}
It's repeats:NO if you want it to run only once. You have repeats:YES.
It is [tim invalidate] and not self.tim invalidate
Do not do self.tim = nil, because that is releasing it. invalidate does everything.
For the record, make sure your property is all correct, ie
#property (nonatomic, retain) NSTimer *happyTimer;
and
#synthesize happyTimer;
For the record, you must be on the same thread.
Hope it helps.
Here is all the lines of code cut from a working production example:
NSTimer *ttt;
#property (nonatomic, retain) NSTimer *ttt;
#synthesize ttt;
self.ttt = [NSTimer scheduledTimerWithTimeInterval:7.00
target:self selector:#selector(ringBell) userInfo:nil repeats:YES];
if ( [ttt isValid] )
[ttt invalidate];
[ttt release]; // in dealloc
You need to add some debugging lines NSLog(#"I just invalidated"); and so on, to make sure you don't have some basic mistake.
Your code seems correct. Usually this problem is starting twice the timer. You can try
-(void)timerStart {
[self.tim invalidate];
self.tim = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(TimerCallback) userInfo:nil repeats:YES];
}
I have 2 ViewController(RootViewController is UITabBarController, ViewController1 links to the item of UITabBarController)
in RootViewController
-(void)startTimer:(NSInteger)v;
{
[NSTimer scheduledTimerWithTimeInterval:10
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
- (void)timerFired:(NSTimer *)timer {
[vViewController1 doSomething];
}
in ViewController1
-(void)doSomething;
{
//I set breakpoint but never be fired
}
timerFired is activated but the function doSomething in ViewController1 never been fired.
Welcome any comment
Thanks
interdev
If you know for a fact that timerFired: is being called, then the only reason that doSomething won't get called is if vViewController1 is nill. Check that again.
The self in scheduledTimerWithTimeInterval target:self means RootViewController, so it will only invoke doSomething in RootViewController but not in ViewController1.