0

所以,我一直在研究如何将块作为选择器传递给按钮,答案似乎比我需要的要复杂。

如果我将 UILabel 子类化为一个名为的方法doBlock;和一个名为的块变量blockToDo,并且所有方法都是调用blockToDo ();,那么我不能这样做:

myLabel.blockToDo = ^myBlock;   
[myButton addTarget: myLabel action: @selector (doBlock) forControlEvents: UIControlEventTouchUpInside];

或者这会让我陷入某种我不知道的麻烦?

编辑:所以,这里有两件事:我真正想做的事情,以及我提出的问题的答案。它们是不同的东西。

表达我的问题的另一种方式可能是将其一分为二。一半是“如果我想向 UILabel 添加一个简单的方法,我可以将其子类化并添加该方法,还是 UILable 的子类有义务做很多其他事情?” 另一半是“向doBlock;子类添加方法似乎是将块作为选择器传递的最简单方法,但这些板上的所有建议似乎都是为此目的定义一个全新的类,这似乎是很多额外的工作。为什么?

似乎大多数人都解决了第二个问题,这是可以理解的,因为它实际上是所述原始问题中更明显的部分。

但是,至于我真正想做的事情:我最终要做的是定义一个具有doBlock;方法的类别,并使用关联引用^myBlockivar 存储在该类别中。这是非常通用的,因为我可以使用类别将块添加到任何类上,然后它会响应@selector (doBlock).

所以,我不知道如何结束这个。我提出的问题已得到部分回答,但事实证明,我真正想做的并不是与所提出的问题直接相关。我应该如何授予最佳答案?

4

3 回答 3

3

我会做类似以下的事情。您还可以创建一个使这更容易的类别。注意addTarget:action:forControlEvents:不保留目标。

更新:如果您使用 ARC,最好的解决方案可能是创建一个将自身分配为关联对象的类别。但是,看看我多久以前写过这个答案,可能有更好的解决方案可用。

BlockExecutor *executor = [BlockExecutor executorWithBlock:^(id sender) {

}];

[myButton addTarget:executor action:@selector(invokeWithSender:) forControlEvents: UIControlEventTouchUpInside];

块执行器.h

typedef void (^BlockExecutorBlock)(id);

@interface BlockExecutor : NSObject

@property(nonatomic, copy)BlockExecutorBlock block;

+ (BlockExecutor*)executorWithBlock:(BlockExecutorBlock)block;

@end

块执行器.m

@implementation BlockExecutor
@synthesize block = _block;;

+ (BlockExecutor*)executorWithBlock:(BlockExecutorBlock)aBlock
{
    BlockExecutor *executor = [[BlockExecutor alloc] init];
    executor.block = aBlock;

    return [executor autorelease];
}

- (void)dealloc
{
    self.block = nil;
    [super dealloc];
}

- (void)invokeWithSender:(id)sender
{
    if(_block)
    {
        _block(sender);
    }
}

@end
于 2012-08-04T23:00:15.923 回答
1

您所描述的不会像崩溃或内存泄漏那样“引起麻烦”。

但是,这很可能违反了 MVC 设计模式。通常在 MVC 中,按钮(即视图)向控制器发送消息。然后控制器或者直接更新标签(另一个视图)(如果按钮操作不应该改变模型),或者控制器修改模型,这导致标签被适当地更新。

于 2012-08-04T23:25:36.847 回答
0

使用这种方法,您可以很容易地结束一个保留周期。假设块引用了控制器:

label.blockToDo = ^{
    [controller didTapLabel];
}

该块将保留控制器,因此无法释放控制器。由于控制器永远不会收到它的最终版本,它不会删除它的视图,标签也不会释放回调块。

您可以通过注意块中的内容来解决此问题,但我认为将块保留在控制器中并通过附加到标签的目标/操作的选择器调用它会更干净。

于 2012-08-06T20:32:44.783 回答