How do I schedule a method to run after a delay - iphone

I want to be able to setup a timer to count for 23 seconds then perform a function. How could I do this? Would I need NSTimer?

Just use
[NSTimer scheduledTimerWithTimeInterval:23.0 target:self selector:#selector(myThingToDo) options:nil];
Typed on mobile, test first.
Also, there's a neat category available that allows you to use NSTimer with Blocks!

You could use GCD methods directly, which saves having to write a separate callback function:
// Just for clarity I'm defining the time period separately, 23 seconds from now.
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, 23 * NSEC_PER_SEC);
dispatch_after(delay, dispatch_get_main_queue(), ^{
// Anything in here will be run on the main queue 23 seconds from now.
});

Related

Need to implement timeout mechanism for UIRefreshControl.

Apple's new UIRefreshControl in iOS 6 is a welcome new feature, but it seems that there is no built-in timeout mechanism.
Here's the scenario why I need it:
Let's say the user pulls the refresh. It goes into the spinning mode, while the code tries to fetch data from the server. The server does not repond and will cause spinning wheel to spin forever. So, there should be a time out mechanism to stop it.
What's the best way to implement it?
First setup a timer with the amount of time you need. Ask it to check the following.
You can use the following property to check whether it is still refreshing after some time
#property (nonatomic, readonly, getter=isRefreshing) BOOL refreshing
If it is then you can stop it using
endRefreshing
Something like :
-(void)checkAndStop{
if(refreshControl.refreshing == YES)
// show an alert if you want
[refreshControl endRefreshing];
}
Also consider using dispatch_after, which might be less consumable than creating NSTimer.
int64_t delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
code to be executed on the main queue after delay
});
I have implemented using NSTimer to end the refreshing:
[NSTimer scheduledTimerWithTimeInterval:60 target:self selector:#selector(handleDataRefreshFailure:) userInfo:nil repeats:NO];
Swift version:
let delayInSeconds: UInt64 = 2
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * NSEC_PER_SEC))
dispatch_after(popTime, dispatch_get_main_queue(), {
if refreshControl.refreshing {
refreshControl.endRefreshing()
}
})

call function after defined seconds without using timer

I am calling a function after 180 seconds using timer. But the timer sometimes behaves in different manner and calls the function multiple times in 180 seconds.
please suggest me how to call a function after each 180 seconds untill I post stop message without using timer.
Code
if(!tmr_CallWebService)
{
tmr_CallWebService = [NSTimer scheduledTimerWithTimeInterval:180 target:ClassTracing selector:#selector(startLocationTracing) userInfo:nil repeats:YES];
}
Thanks in advance
I think there is a method to do this task, here use it like this
[self performSelector:#selector(yourMethodName) withObject:[NSArray arrayWithObjects:firstArgument,secondeArgument,nil] afterDelay:180];
use nil in place of array if you have no argument in that method.
You can use - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay from NSObject

check for time duration during loop

I am using MBProgressHUD to display a progress indicator. The delegate that is called when the indicator is shown is:
- (void)myTask {
while (self.show_progress == NO){
}
}
basically when it goes out of the loop it dismisses the indicator. Now the issue is that I would like do something more in this method. I would like to check for how long has the indicator been spinning for, if it has been more than 5 seconds then I would like to re-load the request. The question is how do I check for this?
This is just to prevent the apps waiting for an infinite amount of time just in case the response never got back or got stuck somewhere.
I'm not familiar with MBProgressHUD , but on general terms you could do the following:
When you first make the request do:
NSDate *startTime = [NSDate date];
Then whenever you want to check how long has it been:
NSTimeInterval timePassed = -[startTime timeIntervalSinceNow];
timePassed will have the value, in seconds, of how long has it been since you made your request. May be you should consider using NSTimer for this: Schedule a timer that will fire 5 seconds after you performed your request, if it triggers cancel the request but if you receive a response before the timer triggers invalidate the timer.
If I understand correctly, your code just waits until the property show_progress becomes NO. I don't know why your code does this, it seems a little inelegant. If you want to keep it this way, at least use a condition lock to prevent the 100% CPU usage:
Prepare the condition lock like this:
NSConditionLock *progressLock = [[NSConditionLock alloc] initWithCondition:0];
In your second thread, once your loading stuff or whatever finishes, change the condition like this:
[progressLock lock];
[progressLock unlockWithCondition:1];
And in your method, do this:
- (void)myTask {
NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:5];
if ([progressLock lockWhenCondition: 1 beforeDate:timeoutDate) {
// we aquired the lock, processing has finished
[progressLock unlock];
} else {
// we didn't aquire the lock because the 5 seconds have passed
// reload the request or do whatever you want to do
}
}
This method waits 5 seconds, and then times out. It uses no CPU in those 5 seconds, because it waits for a signal at the lockWhenCondition:beforeDate: call.
The way I've gone about similar situations is to set up a timer. The basic concept would be to start the timer when the indicator starts spinning. Then invalidate it when the indicator stops. Else if it goes on for 5 seconds, execute your method.
So in your header, you'll want
NSTimer *myTimer;
then in the implementation, when you start the indicator spinning,
[indicator startAnimating];
if (myTimer != nil) {
[myTimer invalidate];
myTimer = nil;
}
myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(reloadRequest) serInfo:nil repeats:NO];
when you stop the indicator from spinning, send [myTimer invalidate]; and myTimer = nil;. If the specified time is reached beforehand, reload the request in your reloadRequest method

How can I trigger a method every 10 seconds without using NSTimer?

I would like to call a method every 10 seconds, but I want to use something other than NSTimer. What could I use to do this?
I know you said you didn't want to use timers, but just to make sure you know how simple it would be with a timer...
[NSTimer scheduledTimerWithTimeInterval:10.0
target:self
selector:#selector(someMethod)
userInfo:nil
repeats:YES];
If you dont want to use the timer, you can use GCD which internally will make use of NSOperationQueue, nevertheless will work in all cases. For eg: i had a class which was inherited from NSOperation so the above methods didn't work so i had go go with GCD:
double delayInSeconds = 3.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(popTime, queue, ^{
[self methodYouWantToCall];
});
The above code calls the method methodYouWantToCall after every three seconds.
You can create a loop with performSelector:withObject:afterDelay: setting afterDelay to 10.0.
I don't recommend this though, use an NSTimer.
- (void)callMeEvery10Seconds
{
[self performSelector:#selector(callMeEvery10Seconds)
withObject:nil
afterDelay:10.0];
// ... code comes here ...
}
If you are not using Cocos2D, you have to use a NSTimer to do this....
If you are using Cocos2D, use the schedule method
here's a link below that shows both :
How can I create a count down timer for cocos2d?
The easiest way to do so is:
- (void)scheduleLoopInSeconds:(NSTimeInterval)delayInSeconds
{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_after(popTime, queue, ^{
[self callWhatEverMethodYouWant];
[self shceduleLoopcaInSeconds:delayInSeconds];//set next iteration
});
}
// now whenever you like call this, and it will be triggering "callWhatEverMethodYouWant" every 10 secs.
[self shceduleLoopcaInSeconds:10.0];

Objective C equivalent to javascripts setTimeout?

I was wondering whether there is a solution to raise an event once after 30 seconds or every 30 seconds in CocoaTouch ObjectiveC.
The performSelector: family has its limitations. Here is the closest setTimeout equivalent:
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 0.5);
dispatch_after(delay, dispatch_get_main_queue(), ^(void){
// do work in the UI thread here
});
EDIT:
A couple of projects that provide syntactic sugar and the ability to cancel execution (clearTimeout):
https://github.com/Spaceman-Labs/Dispatch-Cancel
https://gist.github.com/zwaldowski/955123
There are a number of options.
The quickest to use is in NSObject:
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay
(There are a few others with slight variations.)
If you want more control or to be able to say send this message every thirty seconds you probably need NSTimer.
Take a look at the NSTimer class:
NSTimer *timer;
...
timer = [[NSTimer scheduledTimerWithTimeInterval:30.0 target:self selector:#selector(thisMethodGetsFiredOnceEveryThirtySeconds:) userInfo:nil repeats:YES] retain];
[timer fire];
Somewhere else you have the actual method that handles the event:
- (void) thisMethodGetsFiredOnceEveryThirtySeconds:(id)sender {
NSLog(#"fired!");
}
+[NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:]
Documentation
You may also want to look at the other NSTimer methods