-2

Basically this is what I like to do:

-(void)didBeginContact:(SKPhysicsContact *)contact
{
     uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);
     if (collision == (CNPhysicsCategoryCat|CNPhysicsCategoryBed)) {
         _catNode.userData = [@{@"catOnBed":@(YES)} mutableCopy];
         //Code here can let me wait for 3 seconds or something.
         (_catNode.userData[@"catOnBed"])?[self win]:[self lose];
     }
     if (collision == (CNPhysicsCategoryCat|CNPhysicsCategoryEdge)) {
         [self lose];
     }
}

So I want the detection be done 3 seconds after the contact happens.

I tried dispatch_time method and it returns "breakpoint 2.1" to me. Screenshots below:

Breakpoint 2.1 Breakpoint 2.1

Then I also tried performSelector method and it tells me undeclared "detectContact..."

detectContact

I also created the method, here is the evidence.

evidence

And then I tried SKAction sequence method (I think this one is closed). And it failed too:

SKAction sequence

And here is the stack trace:

Stack Trace

Aero Wang
  • 8,382
  • 14
  • 63
  • 99
  • possible duplicate of [How can I delay a method call for 1 second?](http://stackoverflow.com/questions/920675/how-can-i-delay-a-method-call-for-1-second) – maelswarm Apr 01 '14 at 00:42
  • After reading it I don't think it's the same question because I am calling a method here and that question is about creating a delay through the original method. – Aero Wang Apr 01 '14 at 00:54
  • 3
    I get the feeling that you're not even sure on what you're asking. Besides the breakpoint images you're posting are essentially useless without the proper error returned and the stack trace. – Can Apr 01 '14 at 01:03
  • Here is the stack trace: http://i.stack.imgur.com/9B9Tt.png – Aero Wang Apr 01 '14 at 01:06
  • Ok, getting closer. The one on the left is the stack trace, the one on the right is plain assembly, which is useless unless you're a magician. Go to the console on the bottom, and paste the console output, the specific error should be there. – Can Apr 01 '14 at 01:08
  • The error just says, "(lldb)." What does this mean and why does it exist? – Aero Wang Apr 01 '14 at 01:10
  • That's the lldb command prompt, what else is there above it? Also a breakpoint is not an error: https://developer.apple.com/library/ios/recipes/xcode_help-source_editor/Creating,Disabling,andDeletingBreakpoints/Creating,Disabling,andDeletingBreakpoints.html – CodeSmile Apr 01 '14 at 07:22

4 Answers4

2

You'd could use a delayed task!

int64_t delay = 3;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^(void){
    // do whatever you want to do after 3 seconds.
});
Tillson
  • 530
  • 2
  • 14
2

You can use -[NSObject performSelector:withObject:afterDelay]. For more information look at the documentation. Basically your code would look like this:

-(void)didBeginContact:(SKPhysicsContact *)contact {
    // Other code
    [self performSelector:@selector(detectContact) withObject:nil afterDelay:3];
}

- (void)detectContact {
    // Code to be execute after 3 second delay
}

The method detectContact would be called after 3 seconds.

drewag
  • 93,393
  • 28
  • 139
  • 128
  • It says undeclared identifier. Screenshot: http://i.stack.imgur.com/zbYWm.png – Aero Wang Apr 01 '14 at 00:52
  • You will have to define the "detectContact" method. That was just an example method name. That method will hold whatever code you want to execute after the delay. – drewag Apr 01 '14 at 00:53
  • Where do I define this method and how do I define it while calling out the original method shown above? – Aero Wang Apr 01 '14 at 01:03
  • You declare and implement it like any other method. I added an example to my answer. – drewag Apr 01 '14 at 01:12
  • Thanks man. It still shows the same information: http://i.stack.imgur.com/4VuMA.png – Aero Wang Apr 01 '14 at 01:18
  • Oh sorry, I forgot to include "selector" as I didn't write and compile this in an editor first. Simply change `@(detectContact)` to `@selector(detectContact)`. (I also updated my answer). – drewag Apr 01 '14 at 01:20
1

Use dispatch_time_t like so...

double delaySeconds = 2.0;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC));
dispatch_after(time, dispatch_get_main_queue(), ^(void){
    (_catNode.userData[@"catOnBed"])?[self win]:[self lose];
});
maelswarm
  • 1,163
  • 4
  • 18
  • 37
1

Introduce a new SKAction with a delay.

SKAction *delayedBlock = [SKAction sequence:@[[SKAction waitForDuration:2.0], 
                                              [SKAction runBlock:
^{
    // Perform action here.
}]]];

Then run it on whichever node is relevant, possibly being the SKScene

// Assuming that self is the SKScene
[self runAction:delayedBlock];

I would suggest using SKActions over the other suggested alternatives, to be confined within the run loop of SpriteKit.

Can
  • 8,502
  • 48
  • 57
  • I think this one is the solution (or at least very closed). I still run into break point 1.1 tho: http://i.stack.imgur.com/b3kby.png – Aero Wang Apr 01 '14 at 01:01
  • 2
    [A breakpoint isn't an error](http://stackoverflow.com/questions/10016890/thread-1-stopped-at-breakpoint-error-when-initializing-an-nsurl-object/10016939#10016939), @AeroWindwalker. – jscs Apr 01 '14 at 01:03
  • For some reason it appears to run the desired action twice instead of just once if this method is used. – Aero Wang Apr 01 '14 at 01:31
  • Probably because collisions occur multiple times? Make sure you only fire once. – Can Apr 01 '14 at 01:32
  • It's odd because other methods will not result at this phenomenon. – Aero Wang Apr 01 '14 at 07:58