UIBarButtonItem : 대상 작업이 작동하지 않습니까?


80

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

답변:


126

UIBarButtonItem의 대상과 동작이 사용자 지정보기에 적용되지 않는다고 생각합니다. UIImageView 대신 UIButton을 사용하고 버튼에 대상과 작업을 적용 해보십시오.

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

31
감사. UIBarButtonItem에서 상속 UIBarItem하고 NSObject그것은 그래서는 접촉에 대해 아무것도 알지 못한다. 문서 에서 사용자 정의보기가 UIButton 인 경우에만 actiontarget속성이 적용 된다고 언급하면 ​​좋을 것 입니다.
Jason Moore

18
@JasonMoore : 더 좋은 점은 버튼이 버튼처럼 작동한다면 좋을 것입니다. 프로그래머가 예상 한대로 작동했다면 추가 문서가 필요하지 않습니다.
GeneralMike dec.

정말 고마워. 또한 코드에서 setTarget 및 setAction에 대한 IBOutlet 참조를 사용할 수 있습니다. 그러나 코드에서 UIBarButtonItem을 생성하면 setTarget 및 setAction을 사용할 수 없으며 작동하지 않습니다.
MOBYTELAB

1
이것은 오래된 게시물이지만 어쨌든 이것을 공유하고 싶었습니다. 사용자 지정 뷰가있는 UIBarButtonItem 개체에주의를 기울여야하는 것에 지 쳤기 때문에 실제로 (제 생각에) 작동하는 확장 클래스를 작성했습니다. 여기에서 소스를 찾을 수 있습니다. gist.github.com/tvervest/8708465
Thomas Vervest 2014 년

heh, target 대신 targetForAction을 사용했습니다.
Mathijs Segers 2015-06-22

24

나는 같은 문제가 있었지만 UIButtonUIBarButtonItem(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은 배경 이미지를 표시하는 데 문제가 있습니다. 이 제스처 인식기로 마침내 작동했습니다.
Denis

내 사용자 정의보기에 탭 제스처를 추가하는 것은 작동하지 않았지만 내 바 버튼 항목에 추가하면 작동했습니다.
Ronaldoh1

@ Ronaldoh1 UIBarButtonItem에 UITapgesture를 어떻게 추가 했습니까?
tsuz apr

@ user013948은 모든 뷰에서와 마찬가지로. UIBarButtonItem은 UIView를 하위 클래스로 만듭니다 (오해하지 않은 경우).
Ronaldoh1


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을 사용하여 다른 뷰를 추가 할 수도 있습니다.
Brave

7

비슷한 문제가있었습니다. 그리고 처음에는 @drawnonward가 제안한 경로를 따랐지만 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
이것은 나를 위해 그것을 해결했습니다! 팝 오버와 함께 사용하려면 다음을 사용하십시오. [myPopover presentPopoverFromBarButtonItem : sender allowedArrowDirections : UIPopoverArrowDirectionAny animated : YES];
mpemburn

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

@ohhorob, IB도 사용하지 않습니다;)
Jacob Relkin

또한 대상으로 설정하는 인스턴스가 해제 및 할당 해제되지 않았는지 확인하십시오. 탐색 컨트롤러 하위 클래스입니까 아니면 탐색 계층 구조의 다른 뷰 컨트롤러입니까?
ohhorob

@ohhorob,이 코드는 출시되지 않은 뷰 컨트롤러 내에 있습니다.
Jacob Relkin

deselectAll전화가 안 오는 걸 어떻게 확인 했어 ? 디버거 중단 점을 설정하여 또는 예상 된 결과가 표시되지 않습니까?
ohhorob

1

Swift 3. 바 버튼 항목 내부에 사용자 정의보기가있는 비슷한 문제가있었습니다. 탭이 작동하도록하기 위해 뷰에 제스처를 할당하고 동작을 설정했습니다. 뷰는 할당 할 콘센트 여야했습니다. 이렇게하면 사용자 정의보기에서 작동했습니다.

제스처를 클래스 변수로 설정

@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

사용자 정의보기가 터치 이벤트를 먹거나 부모보기로 전달합니까?


보시다시피 내 사용자 정의보기는 단순한 ol ' UIImageView입니다. 그래서 어떤 이벤트도 먹지 않습니다.
Jacob Relkin

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로 푸시하는 것이 좋습니다).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.