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__"];