NSTimer issue - Stop different timers using single functions - iphone-sdk-3.0

I am creating an application in that I need to use about 20 different Timers.
But all the timers are going to be created at run time, by calling some function.
All the timers might having different timer interval and all timer do have different counters that will be reduced by one with passing of 1 minute.
Now when the counter will become 0 the timer will be stopped. But in my application all timers have different counter values and I want to stop different timers at it's time interval using a single function.
I know that we can create different timers and by providing the selector values to their respective timer functions , we can stop the timer by I don't have idea that how many timers are running at a time , and if I do stop a single timer at a time then it will lead to stop all the timers and the functionality is not showing properly.
Please help me by providing any logic or samples How to stop multiple timers using single function at different time interval.
thanks in advance

I think you may want to reconsider your software design. You can call your method as normal:
[self method];
And then at the end of each method, do the following:
[self performSelector:#selector(method) withObject:nil afterDelay:(1000)];
This will create a loop. You can then increment an integer and do something else when that counter reaches 0. You'll be able to manage your code much more effectively. You may still need timers for some situations, but this will definitely be more efficient than the 20 timers you were planning on using.

Related

Feasibility for adding value to a NSTimer

I am currently making a application using NSTimer as base for recording time. However, in the event that the player used a hint or forfeit on the current question, I would like to have a penalty of increasing time to the on-going NSTimer.
The question I have is, is it possible to add in more value to the on-going NSTimer?
e.g The timer is at 0:23:41.2, and the user press hint/forfeit. I want to have a function that add, lets say 10min. How do I make a function such that the timer will become 0:33:41.2 when the player press hint/forfeit?
I tried finding on google and SO on articles related to NSTimer and came across this SO thread which might be useful. How to value for NSTimer
Instead of elapse time as shown in the thread, I think I could swap it with a variable like below. (But if the example I shown below is not feasible, please enlighten me. I really want to make this game a successful one)
-(BOOL)hintButtonPressed
.
-(void) timerFireMethod:(NSTimer *) theTimer {
if (hintButtonPressed == true) {
// do something to increase value
[theTimer invalidate];
}
}
Even though I would not use a NSTimer for a countdown, there is an easy way to add time to its fireDate:
[_timer setFireDate:[[_timer fireDate] dateByAddingTimeInterval:600]];
This would add 10 minutes (600 seconds) to my _timer.
And the best solution for your example would be to create an action-method for the button and check in that action-method whether the user already got a time bonus.
Of course you can modify the fireDate in the fire method but it won't fire again with my codeline.
NSTimer is not a good tool for tracking time. It's a good tool for scheduling periodic actions (particularly actions that don't have very tight timing requirements).
The way you track time is with three ivars: the most recent "timer start" time, the "accumulated time" (which is the time prior to the most recent start), and an "isRunning" boolean. At any given time, the total time is:
accumulated + (now - start) * (isRunning ? 1 : 0)
With this, you can easily add or subtract time by modifying accumulated. And you don't need an NSTimer to update your data (which is seldom a good approach).
To what i remember, you can't add, increment time to a NSTimer, you need to create a new one, and release / invalidate the older one.
By the way, if it's a simple timer, you still can make it easy
[NSObject cancelPreviousPerformRequestsWithTarget: self]
[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay: incrementedTime];
But you if you performSelector, you cant get precise time information like NSTimer, you can just blind increment time. So all depend of your needs.

How to wait for an event or timeout

I'm trying a simple thread program.
I need to wait for a event and time delay. This time delay is varying. How to do this?
Can anyone explain with a sample program? I know how to spawn a thread with NSThreads as well as through NSInvocationOperation.
If you need to wait for a timeout consider using NSTimer. You can use setFireDate method to modify time delay.
For asynchronous events there's a lot of way to solve the problem, according to what you need in your program: first of all you may simply setting a delegate that receive a message when something happen in your class. If you need something more complex (in order to avoid race conditions or deadlocks) you may consider use NSNotificationCenter or NSConnection.

Idle thread approach in iOS

I'm trying to set up a thread that stays idle until new data it's available. What it's the best approach for this in Objective-C? Till now I tried to make a simple run loop
while(YES) {
if(isDataAvailable) {
//process data
}
}
However this has an huge impact on performance, my FPS drops from 40 to 20 and the interface becomes unusable (even if the actual data process happens once in a second or so and it's not very intense for the CPU. I tried to add [NSThread sleepForTimeInterval:0.01] at the end, but this way I lose data packages ('process data' refers to some streaming related operations, queue and unqueue data packages), however the FPS returns to normal.
I'm fair new in Objective-C and I was thinking maybe there is a better way to do this? I also had a look over NSRunLoop, but didn't manage to make it work as a run loop :), only attached a timer to it that doesn't do more than my [NSThread sleepForTimeInterval:0.01] thing.
Any help it's highly appreciated:D
If you need to keep the seconary thread alive, you definitely want to use a real runloop:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW1
Basically, just create and start your thread, set up an autorelease pool, then run your runloop for some set time amount. When the time expires, you check to see if you should exit your thread, or enter into the runloop again.
As Marcelo points out though, there are more modern approaches to achieve concurrency (GCD and async dispatch being a couple of examples) so maybe investigate other forms of concurrency as well.

NSTimer versus separate thread - which one to choose?

Let's assume we have simple UI and for whatever reason, every 5 seconds a UILabel needs to be updated.
I can now either setup an NSTimer which does the job, or create a separate thread which runs endlessly, sleeps 5 seconds, does its thing, sleeps again and so on.
Which one would I choose to go for? What are the differences?
You have to do UI operations on the main thread anyway, so unless your doing some processing prior to setting the label there would be no benefit of using another thread.
The UI can only be updated on the main thread of any program. If you want to do calculations for the label in a separate thread, that's perfectly fine, but the code to update your UI will have to operate on the main thread (or, you can use performSelectorOnMainThread:withObject:waitUntilDone: to call setText: on your label and have it operate correctly).
Use NSTimer.
Why?
As soon as you introduce extra threads, you introduce the possibility of a whole new class of bugs i.e. thread synchronisation issues. These tend to be very hard to diagnose and resolve due to their indeterminate nature.
You have to do UI updates on the main thread anyway. So your thread would have to do -performSelectorOnMainThread:withObject:waitUntilDone: to update the UI.
If the calculations for the label take a while (don't just assume they do, try it the simple way first and see), have your timer kick off an NSOperation to do the calculations and then have the NSOperations call -performSelectorOnMainThread:withObject:waitUntilDone: when it has finished.

Cocoa - Pause a method

How would I go ahead about pausing a method without freezing the UI, and then continuing the process when told?
Thanks,
Kevin
There's not a way to interrupt execution of an arbitrary method and to then resume it later.
You can break your method into multiple pieces that represent the units of work that you want to be able to pause between. You can then use timers (either NSTimers or [NSObject performSelector:withObject:afterDelay:] for a specific pause interval.
More information on what you're trying to do might allow for some more specifically useful suggestions here.
There is a method to prevent the UI from stopping and eg. timers too. This is more or less the whole reason why we have run loops (well, thats not really true but in your case it is).
Just insert this into your function and everything will work:
while(pauseFunction)
{
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1f]];
}
Remark: Everything scheduled with the runloop keeps running, this is the UI, timers, networking etc. pp.