I'm creating a barButton which when pressed should set the editing mode of a UITableView to yes. Here's my code:
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @"Edit"
style: self.navigationController.navigationItem.leftBarButtonItem.style
target: self
action: ];
What I don't understand is what I need to put as an argument for the action
part so that I can execute a code block there. I could easily enough put @selector(someMethod)
but I'm only executing one or two lines and creating another method is pretty pointless.
Thanks for any help!
Further to pgb's comment, writing something like this would solve the problem:
@interface PJBlockHolder
+ (id)blockHolderWithBlock:(dispatch_block_t)block;
- (void)invoke;
@end
/* obvious implementation; copy the block, issue it upon invoke */
And:
[[UIBarButtonItem alloc] initWithTitle: @"Edit"
style: self.navigationController.navigationItem.leftBarButtonItem.style
target: [PJBlockHolderWithBlock:^{ /* your code here */ }]
action:@selector(invoke) ];
So you've created a custom object that wraps a block and issues it upon a particular selector.
EDIT: as noted below, UIControl
s don't retain their targets. So probably the easiest thing is to tie the lifetime of the block holder to the lifetime of the control; that's not necessarily ideal because then the holder will outlive its usefulness if you subsequently remove it as a target while keeping the control alive, but it's probably suitable for the majority of cases.
Options are either to use Objective-C's built in associated objects, or to use the fact that UIControl
inherits from UIView
, giving it a CALayer
, which can store arbitrary keyed objects.
Justin Spahr-Summers links to a well documented, public domain implementation of the former in his comment below so I'll show an example of the latter, even though it's hacky, for the purposes of discussion.
PJBlockHolderWithBlock *blockHolder = [PJBlockHolderWithBlock:^{ /* your code here */ }];
UIBarButtonItem *barButtonItem =
[[UIBarButtonItem alloc] initWithTitle: @"Edit"
style: self.navigationController.navigationItem.leftBarButtonItem.style
target: blockHolder
action:@selector(invoke) ];
[barButtonItem.layer setValue:blockHolder forKey:@"__myBlockHolderKey__"];
You can't do it as you intend. The target:
action:
parameters are intended to send an object and a selector to be called on that object. As far as I know, there's no equivalent API that uses blocks.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With