Calling a method with arguments after certain time - ios

I want to call a method after certain time.
This is just an example.
- (void)myMethod:(int)value1 setValue2:(CGPoint)value2{
//Do Something with values
}
At first I thought
[self scheduleOnce:#selector(myMethod:setValue2:) delay:timeToWait];
but I can't pass the arguments when using selector, so Im asking you guys for an alternative...What could I do?
Thanks for your time guys and have a great day!

You can try GCD's dispatch_after. For instance:
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self myMethod:someValue setValue2: someValue2];
});

You could put your arguments into an NSDictionary and pass that as the object parameter to - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

Related

Creating a method in objective-c with a delay argument

I'm trying to create a method with an argument in objective-c, the argument is an amount of seconds before the actual method starts.
I'm trying to avoid using the [self performSelector:(SEL) withObject:(id) afterDelay:(NSTimeInterval)]; because having the delay within my method would actually save me a lot of coding as I am planning to add other arguments to this method.
Example of the method:
-(void) startMethodAfterArgumentDelay: (NSTimeInterval *)delay{
NSLog(#"perform action after argument delay");
}
and how to call it:
[self startMethodAfterArgumentDelay:3.0f];
Any help would be greatly appreciated!
If you don't want to use any 3rd party libraries as the other answer suggested, this is easy enough to implement yourself using GCD's dispatch_after(). Just note that this method is a asynchronous, so your method will return immediately even though the contents of the block are delayed.
- (void)startMethodAfterArgumentDelay:(NSTimeInterval)delay
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"perform action after argument delay");
});
}
You can use BlocksKit and then write code like that:
[self bk_performBlock:^(id obj) {
//code
} afterDelay:delay];
Just feed delay to dispatch_after.
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
// do whatever
});

How to declare(?) NSTimer function?

I want to use the following:
class func sleepForTimeInterval(_ ti: NSTimeInterval)
It is a NSTimer function that I found here. I cant figure out how and where to declare the function. I want a 0.1s delay before executing another function.
If you want to do something after 0.1, you can probably try this code:
double delayInSeconds = 0.1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// do something after delay
});
For beginner, it's the best if you can go check out the documentation. Here is the link about NSTimer: https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSTimer_Class/index.html
And I don't think you can do something like what you said by using NSTimer.

NSTimer is not calling in background method

I got stuck in a problem. I'm trying to run a timer in a method which itself is in background resulting my timer is not initiating. I got to know some where that timer can't be initialized in background so is there any way to do this?
You can perform the operation on main thread.
[self performSelectorOnMainThread:#selector(initTimer) withObject:nil waitUntilDone:NO];
and then
- (void)initTimer {
// Init your timer here.
}
You can try Background Fetch in ios7 to run code on background
Try this :
// provide value as required. Time here is 3 sec
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 3.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// do your task
});
As pointed out by #Bryan Chen, you can schedule a method to be run on the current thread using the following code:
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC);
dispatch_after(when, dispatch_get_current_queue(), ^(void) {
[self myTimedMethod];
});
You cannot use NSTimer in a background thread unless you are maintaining a run loop on that thread.

Is the a way to delay dismissModalViewControllerAnimated?

I'd like to pop a display from inside a completion block, but I also want to dismissModalViewControllerAnimated from inside the same block (but AFTER the popup completes). Note that the popup schedules and runs after the completion block execution finishes, which means it never happens since the dismissal is synchronous...
So, a quick fix would be to find a way to schedule the dismissal asynchronously for after the popup. Is there a chaining method? A way to force holding async tasks to run and wait for them?
Use -performSelector:withObject:afterDelay:. You'll need to wrap the dismissal in a selector matching the signature required by -performSelector:..., since dismissModalViewControllerAnimated: takes a BOOL.
You can use dispatch_after instead, and it will be dismissed animatedly. check this simple sample code:
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){
[self dismissModalViewControllerAnimated:YES];
});

Multiple dispatch_after can not work well

It is easy to delay executing something like this
double 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#>
});
But it will make above code fail to execute if putting another longer delay like
double delayInSeconds2 = 3.0;
dispatch_time_t popTime2 = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds2 * NSEC_PER_SEC);
dispatch_after(popTime2, dispatch_get_main_queue(), ^(void){
<#code to be executed on the main queue after delay#>
});
Why just execute the longer one instead of both ? Or am I totally wrong ?
it is a queue, but the position depend on the future fire time instead of enqueue time.
if second one is 1 second, it will be insert before the first one.
if you want them executed concurrently (time slice for single core or real concurrency for multi-core cpu), put them on different queue.

Resources