UIBarButtonItem:目标操作不起作用?


79

我在中有一个自定义视图UIBarButtonItem,可以通过调用来设置-initWithCustomView。我的条形按钮项呈现得很好,但是当我点击它时,它不会调用目标对象上的动作。

这是我的代码:

UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"someImage.png"]];
UIBarButtonItem *bbItem = [[UIBarButtonItem alloc] initWithCustomView:imageView];
self.navigationItem.leftBarButtonItem = bbItem;
[imageView release];
[bbItem setTarget:self];
[bbItem setAction:@selector(deselectAll)];

Answers:


124

我认为UIBarButtonItem的目标和操作不适用于自定义视图。尝试使用UIButton代替UIImageView并将目标和操作应用于按钮。

Swift中的示例代码:

let button  = UIButton(type: .Custom)
if let image = UIImage(named:"icon-menu.png") {
    button.setImage(image, forState: .Normal)
}
button.frame = CGRectMake(0.0, 0.0, 30.0, 30.0)
button.addTarget(self, action: #selector(MyClass.myMethod), forControlEvents: .TouchUpInside)
let barButton = UIBarButtonItem(customView: button)
navigationItem.leftBarButtonItem = barButton

30
谢谢。UIBarButtonItem继承自它UIBarItemNSObject因此它对触摸一无所知。如果文档中提到actiontarget属性仅在自定义视图是UIButton时适用,那就太好了。
詹森·摩尔

18
@JasonMoore:更好的是,如果按钮的行为类似于...按钮,那就太好了。如果它的行为符合程序员的期望,则无需额外的文档。
GeneralMike 2012年

非常感谢。同样,我们可以使用IBOutlet引用在代码中设置setTarget和setAction。但是,如果我们在代码中创建UIBarButtonItem,则无法设置setTarget和setAction,它将无法正常工作。
MOBYTELAB

1
尽管这是一篇过时的文章,但我还是想分享一下。当我厌倦了必须注意具有自定义视图的UIBarButtonItem对象时,我编写了一个扩展类,该类实际上以应有的方式工作。您可以在此处找到源:gist.github.com/tvervest/8708465
Thomas Vervest 2014年

嘿,我用targetForAction代替了target。
Mathijs Segers 2015年

24

我有同样的问题,但是不愿意UIButton为我使用a(而不是自定义)视图UIBarButtonItem(根据drawonward的回答)。

另外,您可以UIGestureRecognizer在自定义视图中使用初始化之前添加一个UIBarButtonItem;这似乎在我的项目中工作。

这就是我修改原始代码的方式:

UIImageView *SOCImageView = [[UIImageView alloc] initWithImage:
                             [UIImage imageNamed:@"cancel_wide.png"]];

UITapGestureRecognizer *tapGesture = 
       [[UITapGestureRecognizer alloc] initWithTarget:self 
                                               action:@selector(deselectAll:)];
[SOCImageView addGestureRecognizer:tapGesture];

SOItem.leftBarButtonItem = 
       [[[UIBarButtonItem alloc] initWithCustomView:SOCImageView] autorelease];
[tapGesture release];
[SOCImageView release];

对我来说什么都没有,只有这种解决方案。自定义视图不允许设置操作。同时,普通的UIButton难以显示背景图像。有了这个手势识别器,它终于解决了。
丹尼斯2014年

将手势添加到我的自定义视图中不起作用,但是当我将其添加到我的条形按钮项中时,它确实起作用了。
Ronaldoh1年

@ Ronaldoh1您如何将UITapgesture添加到UIBarButtonItem?
tsuz 2016年

@ user013948就像您对任何视图一样。UIBarButtonItem子类化UIView(如果我没记错的话)。
Ronaldoh16年


24

这是我的工作方式:

UIButton* infoButton = [UIButton buttonWithType: UIButtonTypeInfoLight];
[infoButton addTarget:self action:@selector(displayAboutUs) forControlEvents:UIControlEventTouchDown];

UIBarButtonItem* itemAboutUs =[[UIBarButtonItem alloc]initWithCustomView:infoButton];
…

9

这是我在UIBarButtonItem内部实现UIButton的方法:

UIButton *logoButton = [UIButton buttonWithType:UIButtonTypeCustom];
[logoButton setImage: [UIImage imageNamed:@"icon.png"] forState:UIControlStateNormal];
logoButton.frame = CGRectMake(0, 0, 30, 30);
[logoButton addTarget:self action:@selector(showAbout:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithCustomView:logoButton];
self.navigationItem.rightBarButtonItem = barItem;
[barItem release];

此解决方案是正确的。我们也可以使用UIButton添加另一个视图。
2015年

7

我有一个类似的问题。我最初遵循@drawnonward建议的路径,但是当我尝试让我的动作在iPad上显示弹出框控制器时遇到麻烦:使用嵌入式UIButton作为自定义视图意味着UIButton是事件的发送者,并且当尝试向其发送仅适用于实际UIBarButtonItems的消息时,popover控制器的presentPopoverFromBarButtonItem:方法崩溃。

我最终找到的解决方案是从一个废弃的UIButton窃取我想使用的图像(“信息”图标),并按如下方式构造UIBarButtonItem:

// Make the info button use the standard icon and hook it up to work
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
UIBarButtonItem *barButton = [[[UIBarButtonItem alloc]        
      initWithImage:infoButton.currentImage
              style:UIBarButtonItemStyleBordered
             target:self
             action:@selector(showInfo:)] autorelease];

使用此初始化程序会产生一个条形按钮,其目标和选择器实际上可以工作。比将图像包装在自定义视图中还容易,但这只是锦上添花。


1
这为我解决了!要与弹出窗口配合使用,请使用以下命令:[myPopover presentPopoverFromBarButtonItem:发送者允许的ArrowDirections:UIPopoverArrowDirectionAny动画:是];
mpemburn 2012年

2

如果您不想使用UIImage并在barbuttonitem中拥有自定义视图,请为barbuttonitem的customview属性设置一个轻击手势识别器

let tap = UITapGestureRecognizer(target: self, action: #selector(goProButtonPressed)) deviceStatusBarButtonItem.customView?.addGestureRecognizer(tap)


1

Jacob,一切看起来都不错,但是您可能没有提供正确的选择器。

您可以验证您的动作是否已实际声明

- (void) deselectAll;

并不是

- (void) deselectAll:(id)sender;

如果是后者,则需要将操作设置为@selector(deselectAll:)。(注意分号以匹配方法声明)

另外,void可能是IBAction,但这与您遇到的这个问题无关。


@ohhorob,我对方法签名很满意。
Jacob Relkin'5

@ohhorob,我也没有使用IB;)
Jacob Relkin 2010年

还要检查您设置为目标的实例没有被释放和取消分配。它是导航层次结构中的导航控制器子类还是其他视图控制器?
ohhorob

@ohhorob,此代码在未释放的视图控制器中。
2010年

您如何确认deselectAll未致电?通过设置调试器断点,还是看不到预期的结果?
ohhorob

1

Swift3。我遇到了类似的问题,在条形按钮项中有一个自定义视图。为了使水龙头工作,我为视图分配了一个手势并设置了动作。该视图必须是为其分配的出口。这样做可以与自定义视图一起使用。

将手势设置为类变量

@IBOutlet weak var incidentView: UIView!
let incidentTap = UITapGestureRecognizer()

在viewDidLoad中

incidentTap.addTarget(self, action: #selector(self.changeIncidentBarItem))
incidentView.addGestureRecognizer(incidentTap)

1

Swift 3:以下是我对按钮自定义和事件处理的完整实现。

override func viewDidLoad() {
    super.viewDidLoad()

    let button = UIButton.init(type: .custom)
    button.setTitle("Tester", for: .normal)
    button.setTitleColor(.darkGray, for: .normal)
    button.layer.borderWidth = 1
    button.layer.cornerRadius = 5
    button.layer.borderColor = UIColor.darkGray.cgColor
    button.addTarget(self, action: #selector(self.handleButton), for: .touchUpInside)

    self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    if let button = self.navigationItem.rightBarButtonItem?.customView {
        button.frame = CGRect(x:0, y:0, width:80, height:34)
    }
}

func handleButton( sender : UIButton ) {
    // It would be nice is isEnabled worked...
    sender.alpha = sender.alpha == 1.0 ? 0.5 : 1.0
}

希望这可以帮助


0

您的自定义视图是吃触摸事件还是将其传递给父视图?


如您所见,我的自定义视图只是一个简单的方法UIImageView。所以,它没有吃任何事件,不。
2010年

0

为了使其易于使用,我在UIBarButtonItem上创建了一个类别,如下所示:

@implementation UIBarButtonItem (CustomButtonView)

- (void)setButtonImage:(UIImage *)image
{
    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setBackgroundImage:image forState:UIControlStateNormal];
    [button sizeToFit];
    [button addTarget:self.target action:self.action forControlEvents:UIControlEventTouchUpInside];
    self.customView = button;
}

- (UIImage *)buttonImage
{
    return [(UIButton *)self.customView imageForState:UIControlStateNormal];
}

@end

在您的客户端代码中,只需使用:

myBarButtonItem.buttonImage = [UIImage imagedNamed:@"image_name"];

通过这种方式,您仍然可以在IB中挂接目标和操作(将尽可能多的UI配置推入IB是一件好事)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.