wake-up-neo.com

Parameter für die Tastenaktion übergeben: @selector

Ich möchte die Film-URL von meiner dynamisch generierten Schaltfläche an MediaPlayer übergeben:

[button addTarget:self action:@selector(buttonPressed:) withObject:[speakers_mp4 objectAtIndex:[indexPath row]] forControlEvents:UIControlEventTouchUpInside];

aber action:@selector() withObject: funktioniert nicht?

Gibt es eine andere Lösung?

Danke für die Hilfe!

48
Pascal Bayer

Bearbeiten. Einen ordentlicheren Weg gefunden!

Ein Argument, das die Schaltfläche erhalten kann, ist (id)sender. Dies bedeutet, dass Sie eine neue Schaltfläche erstellen können, die von UIButton erbt und die anderen beabsichtigten Argumente speichern kann. Hoffentlich veranschaulichen diese zwei Ausschnitte, was zu tun ist.

  myOwnbutton.argOne = someValue
  [myOwnbutton addTarget:self action:@selector(buttonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];

und

- (IBAction) buttonTouchUpInside:(id)sender {
  MyOwnButton *buttonClicked = (MyOwnButton *)sender; 
  //do as you please with buttonClicked.argOne
}

Dies war mein ursprünglicher Vorschlag.

Es gibt eine Möglichkeit, das gleiche Ergebnis zu erzielen, aber es ist nicht schön. Angenommen, Sie möchten Ihrer navigate-Methode einen Parameter hinzufügen. Mit dem folgenden Code können Sie diesen Parameter nicht an navigate übergeben. 

[button addTarget:self action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Um dies zu umgehen, können Sie die Navigation method in eine eigene Klasse verschieben und die "Parameter" als Attribute dieser Klasse festlegen ...

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Natürlich können Sie die Navigationsmethode in der ursprünglichen Klasse beibehalten und von navAid aufrufen, solange sie weiß, wo sie zu finden ist.

NavigationAid *navAid = [[NavigationAid alloc] init];
navAid.whereToCallNavigate = self
navAid.firstParam = someVariableOne
navAid.secondParam = someVariableTwo
[button addTarget:navAid action:@selector(navigate) forControlEvents:UIControlEventTouchUpInside];

Wie ich schon sagte, es ist nicht schön, aber es hat für mich funktioniert und ich habe niemanden gefunden, der eine andere funktionierende Lösung vorschlägt.

60
WoodenKitty

Ich habe eine Lösung gefunden. Der Anruf:

-(void) someMethod{
    UIButton * but;
    but.tag = 1;//some id button that you choice 
    [but addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
}

Und hier heißt die Methode:

-(void) buttonPressed : (id) sender{
    UIButton *clicked = (UIButton *) sender;
    NSLog(@"%d",clicked.tag);//Here you know which button has pressed
}
32
orafaelreis

Ich habe eine Lösung gemacht, die zum Teil auf den obigen Informationen basiert. Ich habe einfach titleLabel . text auf die Zeichenfolge gesetzt, die ich übergeben möchte, und setze titleLabel.hidden = YES

So was :

    UIButton *imageclick = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
    imageclick.frame = photoframe;
    imageclick.titleLabel.text = [NSString stringWithFormat:@"%@.%@", ti.mediaImage, ti.mediaExtension];
    imageclick.titleLabel.hidden = YES;

Auf diese Weise ist keine Vererbung oder Kategorie erforderlich und es gibt keinen Speicherverlust

12
Trausti Thor

Sie können eine UIButton-Klasse namens MyButton subclassieren und den Parameter über die Eigenschaften von MyButton übergeben.

Rufen Sie dann den Parameter vom (ID) -Sender zurück. 

11
AechoLiu

Fügen Sie dem Parameter das ausgeblendete titleLabel hinzu, ist die beste Lösung.

Ich habe ein Array arrUrl erstellt, das die NSURL der mov-Dateien in meinem Telefonalbum speichert, indem die Blockierung der Assets blockiert wird.

Danach greife ich bei Frame, sagen wir, das Frame um 3:00 Sekunden in die Filmdatei und generiere die Bilddatei aus dem Frame. 

Führen Sie als Nächstes eine Schleife über die arrUrl aus, und verwenden Sie das Programm, um die Schaltfläche mit dem Bild in der Schaltfläche zu generieren. Hängen Sie die Schaltfläche an die Unteransicht der self.view an.

Da ich die Film-URL an die Funktion playMovie übergeben muss, muss ich die button.titleLabel.text mit einer Film-URL zuweisen. und die Funktion der Schaltflächenereignisse rufen die URL aus der buttontitleLable.txt ab.

-(void)listVideos

{
   for(index=0;index<[self.arrUrl count];index++{
      UIButton *imageButton = [UIButton buttonWithType:UIButtonTypeCustom];
      imageButton.frame = CGRectMake(20,50+60*index,50,50);

      NSURL *dUrl = [self.arrUrl objectAtIndex:index];

      [imageButton setImage:[[UIImage allow] initWithCGImage:*[self getFrameFromeVideo:dUrl]] forState:UIControlStateNormal];
      [imageButton addTarget:self action:@selector(playMovie:) forControlEvents:UIControlEventTouchUpInside];
      imageButton.titleLabel.text = [NSString strinfWithFormat:@"%@",dUrl];
      imageButton.titleLabel.hidden = YES;

      [self.view addSubView:imageButton];
   }
}

-(void)playMovie:(id) sender{
   UIButton *btn = (UIButton *)sender;
   NSURL *movUrl = [NSURL URLWithString:btn.titleLabel.text];
   moviePlayer = [[MPMoviePlayerViewController alloc] initWithContentURL:movUrl];
   [self presentMoviePlayerViewControllerAnimated:moviePlayer];
}

-(CGIImageRef *)getFrameFromVideo:(NSURL *)mUrl{
   AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:mUrl option:nil];
   AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
   generator.appliesPreferredTrackTransform = YES;
   NSError *error =nil;
   CMTime = CMTimeMake(3,1);
   CGImageRef imageRef = [generator copyCGImageAtTime:time actualTime:nil error:&error];
   if(error !=nil) {
      NSLog(@"%@",sekf,error);
   }

   return @imageRef;
}
3
showmyroutes

tl; dr: Verwenden Sie Blöcke

Für Obj-C gibt es beispielsweise einen CocoaPod SHControlBlocks , dessen Verwendung folgendermaßen wäre:

[self.btnFirst SH_addControlEvents:UIControlEventTouchDown withBlock:^(UIControl *sender) {
    [weakSelf performSegueWithIdentifier:@"second" sender:nil];
    NSLog(@"first");
  }];

Für Swift liebe ich die Pod Actions , die Blöcke für UIControls [1] erlaubt:

// UIControl
let button = UIButton()
button.add(event: .touchUpInside) {
    print("Button tapped")
    playMusic(from: speakers_mp4, withSongAtPosition: indexPath.row)
}

Nicht, dass jemand einen 3 Jahre alten Thread liest. :: Grillen ::

[1] Und UIView, UITextField, UIGestureRecognizer, UIBarButtonItem, Timer (formal NSTimer) und NotificationCenter (formal NSNotificationCenter).

1
AmitaiB

Ich denke, die richtige Methode sollte sein: - (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents

UIControl-Referenz

Woher bekommst du deine Methode?

Ich sehe, dass Ihr Selektor ein Argument hat, dieses Argument wird vom Laufzeitsystem gefüllt. Sie werden den Button durch dieses Argument zurückschicken.

Ihre Methode sollte folgendermaßen aussehen:

- (void)buttonPressed:(id)BUTTON_HERE { }

1
vodkhang

Sie können das Tag der Schaltfläche festlegen und vom Absender in Aktion darauf zugreifen

[btnHome addTarget:self action:@selector(btnMenuClicked:)     forControlEvents:UIControlEventTouchUpInside];
                    btnHome.userInteractionEnabled = YES;
                    btnHome.tag = 123;

In der aufgerufenen Funktion

-(void)btnMenuClicked:(id)sender
{
[sender tag];

    if ([sender tag] == 123) {
        // Do Anything
    }
}
1
Fawad Masud

Zum Hinzufügen von Tristans Antwort kann die Schaltfläche zusätzlich zu (id)event auch (id)sender empfangen:

- (IBAction) buttonTouchUpInside:(id)sender forEvent:(id)event { .... }

Dies kann nützlich sein, wenn sich die Schaltfläche beispielsweise in einer Zelle in einer UITableView befindet und Sie die indexPath der Schaltfläche suchen möchten, die berührt wurde sender Element).

0
newenglander

Ich habe in manchen Fällen eine andere Lösung.

speichern Sie Ihre Parameter in einem versteckten UILabel. Fügen Sie dieses UILabel dann als Unteransicht von UIButton hinzu.

wenn Sie auf die Schaltfläche klicken, können Sie alle Unteransichten von UIButton überprüfen. normalerweise nur 2 UILabel drin.

einer ist der Titel von UIButton, der andere ist der, den Sie gerade hinzugefügt haben. Wenn Sie die Texteigenschaft dieser UILabel lesen, erhalten Sie den Parameter. 

Dies gilt nur für Textparameter.

0
LetBulletFlies

UIButton reagiert auf addTarget: action: forControlEvents: da es von UIControl erbt. Es reagiert jedoch nicht auf addTarget: action: withObject: forControlEvents:

siehe Referenz für die Methode und für UIButton

Sie könnten UIButton um eine Kategorie erweitern, um diese Methode zu implementieren.

0
Daniel