wake-up-neo.com

UIBarButtonItem: Zielaktion funktioniert nicht?

Ich habe eine benutzerdefinierte Ansicht in einer UIBarButtonItem, die durch Aufruf von -initWithCustomView..__ festgelegt wird. Mein Bar-Schaltflächenelement wird gut dargestellt, aber wenn ich darauf tippe, wird die Aktion für mein Zielobjekt nicht aufgerufen.

Hier ist mein Code:

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)];
70
Jacob Relkin

Ich denke nicht, dass das Ziel und die Aktion des UIBarButtonItem für benutzerdefinierte Ansichten gelten. Verwenden Sie einen UIButton anstelle von UIImageView und wenden Sie das Ziel und die Aktion auf die Schaltfläche an.

Beispielcode in 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
110
drawnonward

Ich hatte das gleiche Problem, aber es war abgeneigt, eine UIButton anstelle einer benutzerdefinierten Ansicht für meine UIBarButtonItem zu verwenden (pro drawonwards Antwort).

Alternativ können Sie der benutzerdefinierten Ansicht eine UIGestureRecognizer hinzufügen, bevor Sie sie zum Initialisieren von UIBarButtonItem verwenden. das scheint in meinem Projekt zu funktionieren.

So würde ich Ihren Originalcode ändern:

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];
23
Tim Camber

So mache ich es:

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

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

So habe ich den UIButton in UIBarButtonItem implementiert:

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];
9
Zac Witte

Ich hatte ein ähnliches Problem. Ich folgte zunächst dem von @drawnonward vorgeschlagenen Pfad, stieß dann jedoch in Schwierigkeiten, als ich versuchte, einen Popover-Controller auf einem iPad anzeigen zu lassen Die Methode presentPopoverFromBarButtonItem: des Popover-Controllers stürzt ab, wenn versucht wird, ihm Meldungen zu senden, die nur für tatsächliche UIBarButtonItems geeignet sind.

Die Lösung, die ich schließlich fand, bestand darin, das Bild, das ich verwenden wollte (das "Info" -Symbol), aus einem Wegwerf-UIButton zu stehlen und mein UIBarButtonItem wie folgt zu konstruieren:

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

Bei Verwendung dieses Initialisierers wird eine Balkenschaltfläche angezeigt, deren Ziel und Auswahl tatsächlich funktionieren. Es ist auch einfacher als das Bild in einer benutzerdefinierten Ansicht einzuwickeln, aber das ist nur Sahnehäubchen.

7
James Elliott

Swift 3 : Im Folgenden finden Sie meine vollständige Implementierung für die Anpassung von Schaltflächen und die Ereignisbehandlung.

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
}

Hoffe das hilft

1
Joe Andolina

Jacob, alles sieht gut aus, aber du hast vielleicht nicht den richtigen Wahlschalter angegeben.

Können Sie überprüfen, ob Ihre Aktion tatsächlich deklariert ist?

- (void) deselectAll;

und nicht

- (void) deselectAll:(id)sender;

Wenn es sich um Letzteres handelt, müssen Sie die Aktion auf @selector(deselectAll:) setzen. (Beachten Sie das Semikolon, um der Methodendeklaration zu entsprechen)

Void kann auch IBAction sein, aber das ist für dieses Problem, das Sie haben, nicht relevant.

1
ohhorob

Wenn Sie sich nicht mit einem UIImage begnügen möchten und eine benutzerdefinierte Ansicht in Ihrem barbuttonitem haben möchten, setzen Sie die Erkennungseigenschaft für die Griffbewegung auf die customview-Eigenschaft Ihres barbuttonitem

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

0
leokwanbt14

Swift 3. Ich hatte ein ähnliches Problem, bei dem ich eine benutzerdefinierte Ansicht im Bar-Button-Element hatte. Um das Tippen auf die Arbeit zu ermöglichen, habe ich der Ansicht eine Geste zugewiesen und die Aktion festgelegt. Die Ansicht musste ein Auslass sein, der ihr zugewiesen werden sollte. Dabei funktionierte es mit der benutzerdefinierten Ansicht.

Festlegen der Geste als Klassenvariable

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

In viewDidLoad

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

Isst Ihre benutzerdefinierte Ansicht Touch-Events oder gibt sie an die übergeordnete Ansicht weiter?

0
Alex Reynolds

Um dies einfach zu machen, habe ich eine Kategorie für UIBarButtonItem erstellt, die folgendermaßen aussieht:

@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

Verwenden Sie in Ihrem Client-Code einfach:

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

Auf diese Weise können Sie Ihre Ziele und Aktionen immer noch in IB verbinden (so viele UI-Konfigurationen in IB wie möglich zu platzieren, ist eine gute Sache).

0
Tylerc230