10

I want to invoke setEditing:animated: on a table view with a slight delay. Normally, I'd use performSelector:withObject:afterDelay: but

  1. pSwOaD only accepts one parameter
  2. the second parameter to setEditing:animated: is a primitive BOOL - not an object

In the past I would create a dummy method in my own class, like setTableAnimated and then call [self performSelector:@selector(setTableAnimated) withObject:nil afterDelay:0.1f but that feels kludgy to me.

Is there a better way to do it?

Bill
  • 44,502
  • 24
  • 122
  • 213

4 Answers4

20

Why not use a dispatch_queue ?

  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){
      [tableView setEditing …];
  });
Marcelo Alves
  • 1,856
  • 11
  • 12
17

You need to use NSInvocation:

See this code, taken from this answer, and I've changed it slightly to match your question:

BOOL yes = YES;
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:[self.tableView methodSignatureForSelector:@selector(setEditing:Animated:)]];
[inv setSelector:@selector(setEditing:Animated:)];
[inv setTarget:self.tableView];
[inv setArgument:&yes atIndex:2]; //this is the editing BOOL (0 and 1 are explained in the link above)
[inv setArgument:&yes atIndex:3]; //this is the animated BOOL
[inv performSelector:@selector(invoke) withObject:nil afterDelay:0.1f];
Community
  • 1
  • 1
Jonathan.
  • 53,997
  • 54
  • 186
  • 290
  • I think using a var name like `BOOL _yes = YES` is a little clearer, since it alleviates a little confusion as to whether you've got a typo (yes vs YES). – gabrielk Jun 08 '14 at 18:01
  • Also just wanted to point out, the reason for using a variable for `YES` instead of just passing the bool directly: `NSInvocation` throws an exception: `[NSInvocation setArgument:atIndex:]: NULL address argument`, [explained in this answer](http://stackoverflow.com/a/11061349/146517). – gabrielk Jun 08 '14 at 18:05
1

The selector setEditing:animated: is not compatible with performSelector:withObject:afterDelay. You can only call methods with 0 or 1 arguments and the argument (if any) MUST be an object. So your workaround is the way to go. You can wrap the BOOL value in an NSValue object and pass it to your setTableAnimated method.

Felix
  • 35,354
  • 13
  • 96
  • 143
0

If you can get your head around it, use an NSInvocation grabber to make an invocation object & call it with a delay with 1 line instead of many: http://overooped.com/post/913725384/nsinvocation

Pierre Houston
  • 1,631
  • 20
  • 33