How to pause PerformSelector from execution? - objective-c

I'm having serious problem whenever I pause the game, since most of my performSelector: has delay, so it will not execute immediately, but thing goes bad if I'm pausing the game then the performSelector is still calling... How should I overcome this?
I know there is one function under NSObject to cancel all the requests but that's not really what i'm looking for because I want the method to continue execute if the player resume the game.

According to cocos2d Best Practices you should not use performSelector:afterDelay directly but use cocos2d scheduler instead:
Try NOT to use Cocoa’s NSTimer. Instead use cocos2d’s own scheduler.
If you use cocos2d scheduler, you will have:
automatic pause/resume.
when the CCLayer (CCScene, CCSprite, CCNode) enters the stage the timer will be automatically activated, and when it leaves the stage it will be automatically deactivated.
Your target/selector will be called with a delta time
Here's how you schedule your method (assuming self is a CCNode):
[self schedule: #selector(tick2:) interval:0.5];
Don't forget to unschedule it in -tick2: if you want to call it once.

Related

How to make a method to wait till another method complete it work in Objective C?

Consider this scenario.
-(void) mainMethod
{
[self subMethod1];
[self subMethod2];
}
My assumption:
When calling the mainMethod, it will call the subMethod1 first, then the subMethod2. But, there is no rule that says "After completing the subMethod1 only, the subMethod2 should get called". If I use some delay lines or some animation with duration in subMethod1, the control won't wait for it completion. It will just start the next process. So, the subMethod2 can be called before the subMethod1 completes its work. Am I right?
Question:
How can I make subMethod2 to wait, till subMethod1 completes its work?
Note: I don't want to place subMethod2 into subMethod1
You should use a completion block (like UIView animations have blocks that are executed after the animations happen).
If you're not familiar with blocks, take a look at Apple's Short Practical Guide to Blocks.

NSTimer and NSRunLoop

My app tracks a user with CLLocationManager. In the delegate call didUpdateToLocation I do all the fun stuff of saving their position. However, I needed a way to test if they had stopped. That away I could stop recording locations and consider their trip over. So I have a NSTimer in CCLocationManager that gets added and removed every time didUpdateToLocation is called. That away it will be initiated when the user stops and CLLocationManager stops getting called.
The only way that I could ever get the NSTimer to work is to do:
[[NSRunLoop mainRunLoop] addTimer:userStoppedMovingTimer forMode:NSRunLoopCommonModes];
Then to remove it:
[userStoppedMovingTimer invalidate];
I've never had to add timers like this in the past. Could someone shed some light as to why this is?
From the documentation:
There are three ways to create a timer:
Use the scheduledTimerWithTimeInterval:invocation:repeats: or
scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: class
method to create the timer and schedule it on the current run loop in
the default mode.
Use the timerWithTimeInterval:invocation:repeats: or
timerWithTimeInterval:target:selector:userInfo:repeats: class method
to create the timer object without scheduling it on a run loop. (After
creating it, you must add the timer to a run loop manually by calling
the addTimer:forMode: method of the corresponding NSRunLoop object.)
Allocate the timer and initialize it using the
initWithFireDate:interval:target:selector:userInfo:repeats: method.
(After creating it, you must add the timer to a run loop manually by
calling the addTimer:forMode: method of the corresponding NSRunLoop
object.)
You were probably using option 1 previously, and now you're using option 2 or 3.

ios - how to cause a delay in the middle of a method

I'm working on a card game and trying to get cards to deal one after the other. I have a method that animated a card from the deck to a player, and in viewDidLoad I call this method four times. The problem is all four cards get dealt simultaneously. How do I stop a method in its tracks for a period of time?
I know that the scheduledTimerWithTimeInterval method calls another method after a delay, but I'm looking for a way to interrupt the current method after calling the deal method once and then continuing with the rest of the current method. sleep() also doesn't work. I tried putting it between calls to the deal method, but it just executed all the sleep()s and then did all the animation at once again. Any help is much appreciated. Thanks!
You are going down the wrong road. Attempting to sleep a method is not the way to approach this. You want to break the task into steps to be performed serially and perform each step only after the previous step is completed.
Say you have a variable called 'cardCounter' and one called 'cardMax'. Then you have a method called 'dealCard'. In viewDidAppear you intialize 'cardCounter` to zero and 'cardMax' to 4 (or however many cards are to be dealt. Then you call the 'dealCard' method.
(actually, you probably want a method called newGame or something since you will likely want to have multiple games and you don't want to tie your game setup to the viewDidAppear event. So in viewDidAppear you would call 'newGame' and do your initialization there.)
- (void)dealCard {
cardCounter++;
if (cardCounter > cardMax){
// all cards are dealt
// call some method to start game
// or do any other set up;
} else {
// call some method to animate the card
// using core animation with a completion handler?
// using a ^block with a completion handler?
// either way, in the completion handler call
// 'dealCard' again
}
A hint. Create a setup method which is called from your init only once! In that setup method you can work with `performSelector" as tomi said. The Selector is "your" method that moves a card from the deck to the player.
(void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

Cocoa Mac Cancel Background Process

I have a void method called 'startTask'.
On button click, I launch 'startTask' in the background as follows:
[self performSelectorInBackground:#selector(startTask) withObject:nil];
I want to cancel this process when a button is clicked, I cannot however figure out how to do this, can anyone please help?
Thanks in advance
I would use NSOperation and NSOperationQueue. These allow for canceling. Threads require much more work for them to get the signal.
Edit-- for an example
Create a simple class that subclasses NSOperation
In your implementation implement a -(void)main(){
} method. This method is called when your operation is executed.
In the file that you want to launch it from create a member variable of NSOperationQueue.
When you want to launch your task create the operation and add it to the queue. it will operate asynchronously and you can cancel it.
Here is a question for iOS but I believe it should be the same for Cocoa NSOperation on the iPhone

use applicationDidBecomeActive to call viewDidLoad

I want to make sure that all my initializations for my views and stuff are handled every time my application starts, even when it is called back after being sent to the background, such as with multitasking.
What's the best way to do this? should i use applicationDidBecomeActive to call viewDidLoad on my viewcontroller directly? I'm guessing this is not wise. I just want to make sure that stuff gets done on load every time the user calls up the app, no matter what state it is in at the time.
I have several apps published that do just that - call viewDidLoad on one or several UIViewControllers from applicationDidBecomeActive.
It works just fine. Apple doesn't object to it either.
However, be aware that if you have allocations in your viewDidLoad you need to either check for already allocated instances or release the instances you allocate in viewDidLoad when your app suspends. The same goes for DB connections that need to be closed, notification listeners, and so on.
As long as you watch for these elements and handle them correctly, the approach is valid and very usable.