2010-05-09 5 views
61

У меня есть пользовательский вид внутри UIBarButtonItem, установленный по телефону -initWithCustomView. Элемент «Моя кнопка» отображается отлично, но когда я нажимаю его, он не вызывает действие на моем целевом объекте.UIBarButtonItem: целевое действие не работает?

Вот мой код:

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)]; 

ответ

103

Я не думаю, что цель и действие 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 
+0

@drawnonward, Большое спасибо! –

+25

Спасибо. 'UIBarButtonItem' наследует от' UIBarItem' и 'NSObject', поэтому он ничего не знает о касаниях. Было бы неплохо, если бы в документах упоминалось, что свойства' action' и 'target' применяются только в том случае, если пользовательский вид является UIButton. –

+12

@JasonMoore: еще лучше, было бы неплохо, если бы кнопки действовали как ... кнопки. Если бы он вел себя так, как этого требует программист, нет необходимости в дополнительной документации. – GeneralMike

1

Джейкоб, все выглядит хорошо, однако вы не можете при условии правильного выбора.

Вы можете убедиться, что ваши действия на самом деле объявлен

- (void) deselectAll; 

и не

- (void) deselectAll:(id)sender; 

Если это последнее, вам нужно будет установить действие на @selector(deselectAll:). (обратите внимание на запятую в соответствии с декларацией метода)

Кроме того, void может быть IBAction, но это не имеет отношения к этой проблеме.

+0

@ohhorob, я уверен о подписи методы. –

+0

@ohhorob, я также не использую IB;) –

+0

также проверяет, что экземпляр, который вы устанавливаете как цель, не освобождается и не освобождается. Является ли это подклассом навигационного контроллера или другим контроллером представления в иерархии навигации? – ohhorob

0

Является ли ваш пользовательский просмотр приемом событий касания или передачей их на родительский режим?

+0

, как вы можете видеть, мой пользовательский вид - это просто простой «UIImageView». Таким образом, он не ест никаких событий, нет. –

23

Вот как я сделать его работу:

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

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

У меня была аналогичная проблема. И я изначально следовал пути, предложенному @drawnonward, но затем столкнулся с трудностями, когда я попытался заставить свои действия представлять собой контроллер popover на iPad. Использование встроенного UIButton в качестве пользовательского представления означает, что UIButton является отправителем события и метод presentPopoverFromBarButtonItem: контроллер сбрасывается при попытке отправить его сообщениям, которые подходят только для реальных UIBarButtonItems.

Решение, которое я в конце концов нашел в том, чтобы украсть изображение Я хотел использовать (значок «Информация») от холостой 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

Это решило это для меня! Для использования с popover, используйте это: [myPopover presentPopoverFromBarButtonItem: отправитель разрешенArrowDirections: UIPopoverArrowDirectionAny animated: YES]; – mpemburn

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 (нажатие так много конфигурации пользовательского интерфейса в IB, как вы можете, это хорошая вещь).

9

Вот как я реализовал UIButton внутри UIBarButtonItem:

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]; 
+0

Это решение является правильным. Мы также можем использовать UIButton для добавления другого представления. – Brave

21

У меня была такая же проблема, но прочь с использованием UIButton вместо пользовательского представления для моего UIBarButtonItem (в ответ drawnonward в).

В качестве альтернативы вы можете добавить 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]; 
+0

Ничего не работало для меня, только это решение. Пользовательское представление не позволяет установить действие. Одновременно с обычным UIButton возникает проблема с отображением заднего изображения. С этим распознавателем жестов он наконец-то проработал. – Denis

+0

добавление tapgesture в мое пользовательское представление не сработало, но оно действительно работало, когда я добавил его в элемент панели. – Ronaldoh1

+0

@ Ronaldoh1 Как вы добавили UITapgesture в UIBarButtonItem? – tsuz

0

Swift 3. У меня была аналогичная проблема, когда я имел настраиваемое представление внутри элемента панели кнопок. Чтобы заставить кран работать, я назначил жест взгляду и установил действие. Представление должно быть выходом для его назначения. Выполняя это, он работал с пользовательским представлением.

Установка жеста как класс переменной

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

В viewDidLoad

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

Если вы не хотите, чтобы урегулировать с UIImage и имеет настраиваемое представление в вашем barbuttonitem, установить кран жест распознаватель к вашему собственному качеству barbuttonitem

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

0

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 
} 

Надеется, что это помогает

Смежные вопросы