如果将UIView添加为子视图,则UIButton目标不起作用

时间:2014-07-17 22:13:00

标签: ios objective-c uiview uibutton

我有UIButton。它有两个子视图。然后我打电话给:

[createButton addTarget:self action:@selector(openComposer) forControlEvents:UIControlEventTouchUpInside];

如果点击UIButton中未覆盖的部分但是其中一个子视图,则可以正常工作。但是,如果我点击其中一个子视图,它就不会触发操作。

在两个子视图中,我.userInteractionEnabled设置为YES

这两个子视图都是纯UIViewsframebackgroundColor

如何点击“{1}}”并点击UIView

由于

编辑:我需要使用UIControlEvents,因为我需要UIControlEventTouchDown。

编辑2:

以下是该按钮的代码。

UIButton

5 个答案:

答案 0 :(得分:30)

为您的子视图设置userInteractionEnabledNO,让触摸通过它们并传递到您的按钮上。

另外,请确保将_verticle.userInteractionEnabled = NO;媒体资源中的horizontal _horizontal.userInteractionEnabled = NO;更改为{{1}},因为我认为这是一个错字。

答案 1 :(得分:1)

请使用下面的代码(将'ViewControllerFilterCategory'替换为您自己的一个+ nibName)将控制器从nib(子一)添加为当前控制器的子控制器,然后将视图添加为子视图。然后,iOS将按预期调用附加到子控制器的操作:

    let vcCats = ViewControllerFilterCategory(nibName: "ViewControllerFilterCategory", bundle: Bundle.main);
    self.addChildViewController(vcCats);
    self.view.addSubview(vcCats.view);

P.S。不要忘记在删除子视图之前调用'removeFromParentViewController'(如下所示):

@IBAction func onCanceled(_ sender: Any) {
    self.removeFromParentViewController()
    self.view.removeFromSuperview()
}

答案 2 :(得分:1)

对于要添加手势目标的视图,必须将isUserInteractionEnabled设置为true。

根据Apple UIView.animate函数的文档,当启用动画时,也会禁用用户交互。

“在动画过程中,将暂时禁用正在被动画化的视图的用户交互。(在iOS 5之前,整个应用程序都将禁用用户交互。”

Check their documentation

因此解决方案是在DispatchQueue.main.asyncAfter内部运行任何动画

如果您要从其中开始另一个动画,也可以在UIView.animate的完成块中使用此调用

例如

UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.7, options: [.curveEaseInOut, .allowUserInteraction], animations: {
                topConstraint.constant = 0
                windowView.layoutIfNeeded()
                oldNotificationView?.removeFromSuperview()
            }, completion: { result in
                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    //Its important to run below animation in asyncAfter as otherwise setting delay for 4 seconds seems to change frame such that tap gesture or touchesBegan is not sent for the view. So execting after delay using dispatch queue is right way for touch events to be fired instead of using animate functions delay.
                    UIView.animate(withDuration: 0.5, delay:0
                        , options: [.curveEaseOut , .allowUserInteraction], animations: {
                        topConstraint.constant = -height
                        windowView.layoutIfNeeded()
                    } , completion: { result in
                        notificationView.removeFromSuperview()
                        self.inAppNotificationView = nil
                    })
                }
            })

UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.7, options: [.curveEaseInOut, .allowUserInteraction], animations: {
            topConstraint.constant = 0
            windowView.layoutIfNeeded()
            oldNotificationView?.removeFromSuperview()
        }, completion: { result in
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                //Its important to run below animation in asyncAfter as otherwise setting delay for 4 seconds seems to change frame such that tap gesture or touchesBegan is not sent for the view. So execting after delay using dispatch queue is right way for touch events to be fired instead of using animate functions delay.
                UIView.animate(withDuration: 0.5, delay:0
                    , options: [.curveEaseOut , .allowUserInteraction], animations: {
                    topConstraint.constant = -height
                    windowView.layoutIfNeeded()
                } , completion: { result in
                    notificationView.removeFromSuperview()
                    self.inAppNotificationView = nil
                })
            }
        })

答案 3 :(得分:0)

我遇到了这个问题。

在我的情况下,我将nib作为子视图加载。

UIViewController *vc = [[[NSClassFromString(@"nib_controller") alloc] initWithNibName:@"nib_name" bundle:nil] autorelease];
[self.view addSubview:vc.view];

进入nib视图(vc.view)所有按钮都没有调用该动作。

[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];


-(IBAction)btnActions:(id)sender{

    // list star buttons for bookmark
    NSLog(@"btnActions tag %d", [sender tag]);

    // bla bla bla
}

我能够触摸按钮,但方法btnActions没有被触发。

然后,我尝试了一些非常简单和逻辑的东西。

在父视图控制器上,我有一个具有相同名称的方法:

-(IBAction)btnActions:(id)sender{

    // list star buttons for bookmark
    NSLog(@"parent btnActions tag %d", [sender tag]);

    // bla bla bla
}

我刚刚在内部添加了NSLog,看看会发生什么。结果显示在日志控制台上:

parent btnActions tag xxx

这在以前的iOS版本中是不可能的。

但是现在,如果从nib控制器视图加载视图,则可以从父视图访问方法。

对于仍然令人困惑的人,请参阅下面的插图

父母 - >一个
孩子>乙

----------
|        | 
|   A    |
|        |
----------
    |
    |--- -(IBAction)btnActions:(id)sender


----------
|        | 
|   B    |
|        |
----------
    |
    |--- -(IBAction)btnActions:(id)sender (the controller have an method with same name as parent)

B.view是从A控制器添加的

----------
|        | 
|   A    |
|        |
----------
    |
    |--- (touching some button -> execute this:

UIViewController *B = [[[NSClassFromString(@"B_controller") alloc] initWithNibName:@"B_name" bundle:nil] autorelease];
[self.view addSubview:B.view]; // The B.view is added as subview.

B.view中的按钮将动作发送到-(IBAction)btnActions

样品

[(UIButton*)[self.view viewWithTag:button_tag] addTarget:self action:@selector(btnActions:) forControlEvents:UIControlEventTouchUpInside];

所有按钮似乎都运行良好,因为它们都可以被触摸或点击(xcode模拟器)。但是没有调用声明为-(IBAction)btnActions的{​​{1}}方法。我坚持解决这个问题好几个小时,直到我意识到行动被发送到B.controller,如上所述。

令人头疼的是,在iOS早期版本中,这是不可能的。

我不确定,但我认为从iOS9开始,我们有这种不同的行为。

应用程序运行良好,直到iOS8。

答案 4 :(得分:0)

对于我来说,下面的按钮有一个.xib文件,我将此.xib添加到了ViewController中。由于在ViewController中为.xib文件设置了限制,@ IBActions拒绝工作。

enter image description here