Need help with a problem.
Goal
I’m putting together an iOS book app that uses NSTimers to fire off several staggered animation events after loading a view. I’ve created a MethodCallerWithTimer class to help me do this (code at bottom).
My Solution So Far
When I use the MethodCallerWithTimer class, I assign the objectOwningMethod as my UIViewController subclass object (it’s a book page), and then the method as an instance method in that class. Here is an example of a method I assign – quite simply turning on some artwork on the screen:
- (void) playEmory {
[emoryRedArt setHidden:NO];
}
My Issue
When I create multiple MethodCallerWithTimer instances then load the view and start them all, I only ever get the FIRST event to happen. None of the other timers call their target methods. I suspect I don’t understand what I’m asking NSRunLoop to do or something similar.
Any thoughts?
Here is my MethodCallerWithTimer class:
@interface MethodCallerWithTimer : NSObject {
NSTimer * timer;
NSInvocation * methodInvocationObject;
NSNumber * timeLengthInMS;
}
- (id) initWithObject: (id) objectOwningMethod AndMethodToCall: (SEL) method;
- (void) setTime: (int) milliseconds;
- (void) startTimer;
- (void) cancelTimer;
@end
And implementation:
#import "MethodCallerWithTimer.h"
@implementation MethodCallerWithTimer
- (id) initWithObject: (id) objectOwningMethod AndMethodToCall: (SEL) method {
NSMethodSignature * methSig = [[objectOwningMethod class] instanceMethodSignatureForSelector:method];
methodInvocationObject = [NSInvocation invocationWithMethodSignature:methSig];
[methodInvocationObject setTarget:objectOwningMethod];
[methodInvocationObject setSelector:method];
[methSig release];
return [super init];
}
- (void) setTime: (int) milliseconds {
timeLengthInMS = [[NSNumber alloc] initWithInt:milliseconds];
}
- (void) startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:([timeLengthInMS longValue]*0.001) invocation:methodInvocationObject repeats:NO];
}
- (void) cancelTimer {
[timer invalidate];
}
-(void) dealloc {
[timer release];
[methodInvocationObject release];
[timeLengthInMS release];
[super dealloc];
}
@end
These look like one-time firings after a delay; have you considered using something like:
where
myObjectis the instance with theplayEmoryroutine andmyDelayis afloatof the seconds you want the OS to wait before making the call?You can find out more information about this flavor of
performSelectorhere.