2

I want to pass a block argument to -performSelector:withObject:afterDelay:. For example, consider this:

[self performSelector:@selector(delayedBlock:) withObject:^{
    // some code in block
} afterDelay:2];

- (void)delayedBlock:(void (^)(void))code {
    code();
}

It works but I am not sure if I need to do something special because of ARC.

iamjustaprogrammer
  • 1,634
  • 2
  • 17
  • 34
  • 1
    Why not replace all of this will a call to `dispatch_after`? It's cleaner and you don't need the extra method. – rmaddy Feb 20 '14 at 22:01
  • Check the discussion here: http://stackoverflow.com/questions/4007023/blocks-instead-of-performselectorwithobjectafterdelay – Merlevede Feb 20 '14 at 22:03

2 Answers2

0

As rmaddy wrote in the comment, there are better ways to perform a block with a delay, but if you want to use performSelector:withObject:afterDelay:, you should copy the block.

[self performSelector:@selector(delayedBlock:) withObject:[^{
    // some code in block
} copy] afterDelay:2];

From Blocks Programming Topics:

Typically, you shouldn’t need to copy (or retain) a block. You only need to make a copy when you expect the block to be used after destruction of the scope within which it was declared. Copying moves a block to the heap.

Sebastian
  • 7,670
  • 5
  • 38
  • 50
0

You can use the GCD directly:

Here's a simple technique, based on GCD, that I'm using:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
      dispatch_get_current_queue(), block);
}

Or use this useful category:

@implementation NSObject (PerformBlockAfterDelay)


- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay 
{
    block = [block copy];

    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block
{
    block();
}

@end

Check out the discussion in this thread: Blocks instead of performSelector:withObject:afterDelay:

Community
  • 1
  • 1
Rafał Sroka
  • 39,540
  • 23
  • 113
  • 143
  • One disadvantage is dispatch_after is not cancellable. PerformSelector is cancellable with cancelPerformSelector. – JoJo Oct 13 '17 at 00:29