执行代码块代替@selector

时间:2012-07-03 20:16:22

标签: iphone objective-c xcode objective-c-blocks

我正在创建一个barButton,按下时应该将UITableView的编辑模式设置为yes。这是我的代码:

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @"Edit"
                                                                             style: self.navigationController.navigationItem.leftBarButtonItem.style
                                                                            target: self
                                                                             action: ];

我不理解的是我需要作为action部分的参数,以便我可以在那里执行代码块。我可以很容易地放@selector(someMethod),但我只执行一两行,创建另一种方法是没有意义的。

感谢您的帮助!

2 个答案:

答案 0 :(得分:8)

继pgb的评论之后,写这样的东西可以解决问题:

@interface PJBlockHolder

+ (id)blockHolderWithBlock:(dispatch_block_t)block;
- (void)invoke;

@end

/* obvious implementation; copy the block, issue it upon invoke */

[[UIBarButtonItem alloc] initWithTitle: @"Edit"
    style: self.navigationController.navigationItem.leftBarButtonItem.style
    target: [PJBlockHolderWithBlock:^{ /* your code here */ }]
    action:@selector(invoke) ];

所以你创建了一个自定义对象,它包装一个块并将其发布到特定的选择器上。

编辑:如下所述,UIControl s不保留其目标。因此,最简单的方法是将块座的寿命与控制器的寿命联系起来;这不一定是理想的,因为如果你随后将它作为目标移除同时保持控件存活,那么持有者将比它的实用性更长,但它可能适合大多数情况。

选项要么使用Objective-C内置的关联对象,要么使用UIControlUIView继承的事实,给它一个CALayer,它可以存储任意键控对象

Justin Spahr-Summers在下面的评论中链接到前者的一个记录良好的公共领域实现,所以为了讨论的目的,我将展示后者的一个例子,即使它很骇人听闻。

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

答案 1 :(得分:2)

你无法按照自己的意愿去做。 target: action:参数用于发送要在该对象上调用的对象和选择器。据我所知,没有使用块的等效API。