如何实现自定义控件的目标动作机制?

Posted

技术标签:

【中文标题】如何实现自定义控件的目标动作机制?【英文标题】:How to implement target-action-mechanism for custom control? 【发布时间】:2009-08-17 16:22:25 【问题描述】:

我将编写我自己的自定义控件,它与 UIButton 非常不同。它是如此不同,以至于我决定从头开始编写它。所以我的所有子类都是 UIControl。

当我的控件在内部被触摸时,我想以目标动作的方式发出一条消息。该类的用户可以对其进行实例化,然后为该事件添加一些目标和操作。

即想象一下我会在内部调用一个方法-fireTargetsForTouchUpEvent。我怎样才能在课堂上保持这种目标-行动-机制?我是否必须将所有目标和动作添加到我自己的数组中,然后在 for 循环中对目标对象调用选择器(动作)?还是有更智能的方法?

我想提供一些方法来为某些事件添加目标和操作,例如修饰事件(我在发生这种情况时通过调用内部方法手动提出)。有什么想法吗?

【问题讨论】:

通常控件有一个目标,每个事件一个选择器。你想要更多吗? 如果我需要,我可以再多一点吗?我认为是的......但不确定 【参考方案1】:

我只是想澄清@Felixyz 所说的话,因为一开始我并不清楚。

如果您要继承 UIControl,即使您要进行自定义事件,也不必跟踪自己的目标/操作。该功能已经存在,您只需在子类中调用以下代码即可触发事件:

[self sendActionsForControlEvents:UIControlEventValueChanged];

然后在实例化您的自定义UIControl 的视图或视图控制器中,就这样做

[customControl addTarget:self action:@selector(whatever) forControlEvents:UIControlEventValueChanged];

对于自定义事件,只需定义您自己的枚举(例如,UIControlEventValueChanged 等于 1 << 12)。只要确保它在UIControlEventApplicationReserved定义的允许范围内

【讨论】:

【参考方案2】:

你的想法是对的。以下是我的做法:

@interface TargetActionPair : NSObject

    id target;
    SEL action;

@property (assign) id target;
@property (assign) SEL action;
+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)selector;
- (void)fire;
@end

@implementation TargetActionPair
@synthesize target;
@synthesize action;

+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)anAction

    TargetActionPair * newSelf = [[self alloc] init];
    [newSelf setTarget:aTarget];
    [newSelf setAction:anAction];
    return [newSelf autorelease];


- (void)fire

    [target performSelector:action];


@end

有了这个类,存储你的目标/动作对就非常简单了:

MyCustomControl.h:

#import "TargetActionPair.h"

@interface MyCustomControl : UIControl

    NSMutableArray * touchUpEventHandlers;


- (id)init;
- (void)dealloc;

- (void)addHandlerForTouchUp:(TargetActionPair *)handler;

@end

MyCustomControl.m:

#import "TargetActionPair.h"

@implementation MyCustomControl

- (id)init

    if ((self = [super init]) == nil)  return nil; 
    touchUpEventHandlers = [[NSMutableArray alloc] initWithCapacity:0];
    return self;


- (void)dealloc

    [touchUpEventHandlers release];


- (void)addHandlerForTouchUp:(TargetActionPair *)handler

    [touchUpEventHandlers addObject:handler];


- (void) fireTargetsForTouchUpEvent

    [touchUpEventHandlers makeObjectsPerformSelector:@selector(fire)];


@end

之后,设置控件如下:

[instanceOfMyControl addHandlerForTouchUp:
         [TargetActionPair pairWithTarget:someController
                                andAction:@selector(touchUpEvent)];

【讨论】:

哇,这是我在这里得到的最大答案;)谢谢!就我而言,我发现 UIControl 似乎已经为我提供了我需要的东西。但是当有特殊的自定义事件需要处理时,你的技术就很棒了! 实际上,对于自定义事件,您可能希望使用 UIControlEventApplicationReserved 位(16 个可用)并调用 -(void)sendActionsForControlEvents:(UIControlEvents)controlEvents; 这里缺少的是一种删除目标/操作的方法,可能还有重复检查。【参考方案3】:

由于您打算继承 UIControl,因此您可以使用

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

使用它,任何类都可以将自己注册为它想要在您的自定义控制器上进行的任何事件的目标。

【讨论】:

以上是关于如何实现自定义控件的目标动作机制?的主要内容,如果未能解决你的问题,请参考以下文章

从自定义控件引用子项

Qt中添加自定义位置Widget

C# wpf 如何实现自定义控件,布局时,大小发生变化,内部绘制的曲线跟随变化?

如何打造Android自定义的下拉列表框控件

自定义组合控件

MFC如何添加自定义控件