Reputation: 958
I have two methods that both create a random sprite node and add it to the scene. Let's call them spriteMethod1
and spriteMethod2
.
I'd like to have a looping method that runs spriteMethod1
, 5 times
, and then spriteMethod2
once. There also needs to be a delay between each time the spriteMethods
are called.
I thought the following might work, but it doesn't:
-(void) addObjects {
for (int i = 0; i < 5; i++) {
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:2];
}
[self performSelector:@selector(spriteMethod2) withObject:nil afterDelay:3];
[self performSelector:@selector(addObjects) withObject:nil afterDelay:5];
}
Upvotes: 3
Views: 1840
Reputation: 4919
Add a timer in your interface:
@property (nonatomic, weak) NSTimer *timer;
schedule a timer somewhere in your code
self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(spriteMethod1) userInfo:nil repeats:YES];
do this
int count = 0;
- (void)spriteMethod1 {
count ++;
// do your work here
if(count == 5) {
// stop the timer
[self.timer invalidate];
// call the other methods
[self performSelector:@selector(spriteMethod2) withObject:nil afterDelay:3];
[self performSelector:@selector(addObjects) withObject:nil afterDelay:5];
}
}
Upvotes: 1
Reputation: 2138
I think your version doesn't work, because the "afterDelay" param is relative to the moment of invocation. You would need to multiply it with "i", in the for loop, and then use 13 and 18 respectively for the last two selectors.
Look into using an NSOperationQueue. You can set its maxConcurrentOperationCount to 1, to ensure it executes its actions sequentially. E.g.
NSOperationQueue * opQueue = [[NSOperationQueue alloc] init];
opQueue.maxConcurrentOperationCount = 1; // this ensures it'll execute the actions sequentially
NSBlockOperation *spriteMethod1Invoker = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 5; ++i)
{
[self spriteMethod1];
sleep(2); // sleep 2 secs between invoking spriteMethod1 again
}
}];
NSInvocationOperation *spriteMethod2Invoker = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(spriteMethod2) object:nil];
[opQueue addOperation:spriteMethod1Invoker];
[opQueue addOperation:spriteMethod2Invoker];
Upvotes: 0
Reputation: 958
I know this might not be the best solution, but it works for me:
-(void)addObjects {
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:2];
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:4];
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:6];
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:8];
[self performSelector:@selector(spriteMethod1) withObject:nil afterDelay:10];
[self performSelector:@selector(spriteMethod2) withObject:nil afterDelay:13];
[self performSelector:@selector(addObjects) withObject:nil afterDelay:18];
}
Upvotes: 1
Reputation: 1288
This out the top of my head.. not sure if it'll do the trick:
- (void)startAddingObjects
{
NSNumber *counter = @(0);
[self performSelector:@selector(addMoreUsingCounter:)
withObject:counter
afterDelay:2];
}
- (void)addMoreUsingCounter:(NSNumber *)counter
{
int primCounter = [counter intValue];
if (primCounter < 5)
{
[self spriteMethod1];
[self performSelector:@selector(addMoreUsingCounter:)
withObject:@(primCounter++)
afterDelay:2];
}
else if (primCounter < 7)
{
[self spriteMethod2];
[self performSelector:@selector(addMoreUsingCounter:)
withObject:@(primCounter++)
afterDelay:3];
}
}
You'll probably still need to relate the delay to the counter to get the exact results you need.
Upvotes: 0
Reputation: 8170
The problem is that you won't see the delay because the selector is enqueued on the thread loop. From the documentation:
This method sets up a timer to perform the aSelector message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.
Another approach is to make the thread sleep for a few seconds.
[self spriteMethod1];
[NSThread sleepForTimeInterval:2.0f];
In this case your User Interface will hang if you don't execute this code in a separate thread.
Upvotes: 0