执行代码块代替@selector

pri*_*nce 4 iphone xcode objective-c objective-c-blocks

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

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle: @"Edit"
                                                                             style: self.navigationController.navigationItem.leftBarButtonItem.style
                                                                            target: self
                                                                             action: ];
Run Code Online (Sandbox Code Playgroud)

我不明白的是我需要把它作为该action部分的参数,以便我可以在那里执行代码块.我可以很容易地放,@selector(someMethod)但我只执行一两行并创建另一种方法是毫无意义的.

谢谢你的帮助!

Tom*_*mmy 8

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

@interface PJBlockHolder

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

@end

/* obvious implementation; copy the block, issue it upon invoke */
Run Code Online (Sandbox Code Playgroud)

和:

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

因此,您创建了一个自定义对象,它包装一个块并将其发布到特定的选择器上.

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

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

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

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__"];
Run Code Online (Sandbox Code Playgroud)

  • @ JustinSpahr-Summers你是对的; 我当然忽略了回忆"UIControl"没有保留他们的目标,这是愚蠢的,因为它显然会导致保留循环.你的`objc_setAssociatedObject`解决方案正是我自己所做的. (3认同)