以编程方式创建的按钮在自定义视图中无法触发事件(iOS)

3
在iOS上,我通过编程创建了一个按钮,但事件没有触发。
UIButton * anyButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[anyButton addTarget:self action:@selector(handleAnyButton:) forControlEvents:UIControlEventTouchUpInside];
anyButton.frame = CGRectMake(150, 350, 22, 22);
[self addSubview:anyButton];

代码放在自定义视图(而不是自定义视图控制器)中,但我无法触发事件。按下动画不显示。自定义视图启用了userInteractionEnabled。 我也尝试在同一视图上使用storyboard创建另一个按钮,那个按钮可以工作。按钮代码在initWithFrame中完成。必须是我没有发现的一些简单错误,我已经为此苦恼了数小时。
编辑:
事件处理程序:
-(void) handleAnyButton:(UIButton *)button
{
    NSLog(@"handleAnybutton called");
}

编辑2: 以上按钮代码是在PKLocationsSelectionView类的[self setup]中完成的。

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self setup];
    }
    return self;
}

这个视图是在视图控制器(PKLocSelectionViewController)中通过程序创建的,该视图控制器负责此层次结构:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    CGFloat fieldsHeight = 88;
    UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];

    [self.view addSubview:view];
}

handleAnyButton方法是如何定义的? - Bejmax
嗨,我编辑了帖子以包括事件处理程序。 - huggie
这对我来说确实有效。但你需要将 [self addSubview:anyButton]; 更改为 [[self view] addSubview:anyButton]; - Zack
这个视图中没有self.view。我是在视图本身中添加这段代码,而不是在视图控制器中。 - huggie
1
这段代码是完全正确的。也许我们需要看更多。 - Adam Lockhart
4个回答

3

看起来您的按钮框架出了问题

anyButton.frame = CGRectMake(150, 350, 22, 22);

超出父级边界

CGFloat fieldsHeight = 88;
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];

是的,我在我的问题中就是想表达那个意思的 ;)。 - Bejmax
谢谢大家。真是个愚蠢的错误,我没意识到。 - huggie

0

编辑2:按钮是否完全包含在容器(PKLocationsSelectionView)视图的坐标内呢?

从你的代码来看,PKLocationsSelectionView的高度为88,而按钮的位置似乎在外面。我认为,如果按钮不被父视图的框架所包含,它将无法接收触摸事件。


我认为这并不重要。对于我在故事板中创建的那个,我尝试使用UIButton它可以工作。我知道因为我以前做过。 - huggie
嗯,我还没有使用过Storyboard,我的所有按钮都使用这个语法,但是它们是在iOS 6之前编写的,对我来说很有效。 - Bejmax
是的,我认为当你写UIButton而不是id时,如果你想访问特定于UIButton的属性,你就不必手动转换它。那是我所知道的唯一区别。 - huggie
谢谢,我还在弄清楚是否被其他视图阻止了。但是那篇文章(由Adam Lockhart发布的?)已经被撤下了。 - huggie
容器视图的CGRect值是什么? - Bejmax
显示剩余5条评论

0

这是对我有效的代码:

MyCustomView.m: 

#import "MyCustomView.h"

@implementation MyCustomView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.frame = CGRectMake(0, 0, 100, 100);
        [button addTarget:self action:@selector(greet:) forControlEvents:UIControlEventTouchUpInside];
        [button setTitle:@"Greet" forState:UIControlStateNormal];

        [self addSubview:button];

        self.backgroundColor = [UIColor greenColor];

    }
    return self;
}

-(void) greet:(id) sender
{
    NSLog(@"greet!");
}

这里是ViewController.m文件:

- (void)viewDidLoad
{
    [super viewDidLoad];

    MyCustomView *view = [[MyCustomView alloc] init];
    view.frame = CGRectMake(0, 0, 100, 100);
    [self.view addSubview:view];

}

0
尝试在viewDidLoad中更改您的视图初始化代码,给出一个静态框架,看看是否有效。
- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    CGFloat fieldsHeight = 88;
    //See the change in below line.. instead of using self.view.bounds.size.width
    // I used a static width.. 320 pixel for the moment..
    UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, 320.0, fieldsHeight)];

    [self.view addSubview:view];
}

viewDidLoad中,控制器的视图层次结构不会完全绘制。因此,self.view.bounds.size.width可能会给出不正确的值。要访问self.view.frameself.view.bounds,您至少应该等到viewWillAppear被调用。
此外,您的按钮原点y坐标为350,在最大高度仅为88的视图中。任何超出父视图框架的控件都无法接收触摸事件。

谢谢!按钮超出了框架。 - huggie
哦,我猜Alexey先赢了,所以我不得不把它给他。抱歉。 :p - huggie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接