Objective C: Sending arguments to a method called by a UIButton

后端 未结 6 715
甜味超标
甜味超标 2021-01-06 10:26

I have a method that is being called when a UIButton is clicked. When I create the button I want it to store an NSTimer as an argument.

This is the timer and the cr

相关标签:
6条回答
  • 2021-01-06 10:59

    Modify your method to take a single NSArray as an argument. Then, create your array of parameters and pass it to performSelector.

    To be more clear:

    You would create the IBAction required for the control's event and a second method that takes an NSArray as an argument. When the IBAction method is called, it would call the second method after creating the NSArray of parameters. Think of it as a "method chain."

    0 讨论(0)
  • 2021-01-06 11:08

    You need to make the timer a property of your view controller and then referenced it from your tapFig: method. Here is what your code might look like:

    MainViewController.h

    //
    //  MainViewController.h
    //  TapFigSample
    //
    //  Created by Moshe Berman on 1/30/11.
    //  Copyright 2011 MosheBerman.com. All rights reserved.
    //
    
    @interface MainViewController : UIViewController  {
        NSTimer *timer; 
        UIButton *stickFig;
    }
    
    @property (nonatomic, retain) NSTimer *timer;
    @property (nonatomic, retain) UIButton *stickFig;
    
    - (void)tapFig:(id)sender;
    
    - (void) moveStickFig;
    
    - (void) moveStickFig:(id)yourArgument
    
    
    @end
    

    MainViewController.m

    //
    //  MainViewController.m
    //  TapFigSample
    //
    //  Created by Moshe Berman on 1/30/11.
    //  Copyright 2011 MosheBerman.com. All rights reserved.
    //
    
    #import "MainViewController.h"
    
    
    @implementation MainViewController
    
    @synthesize timer, stickFig;
    
    - (void) viewDidLoad{
    
        [self  setTimer:[NSTimer scheduledTimerWithTimeInterval:(0.009) target:self selector:@selector(moveStickFig:) userInfo:stickFig repeats:YES]];
        [stickFig addTarget:self action:@selector(tapFig:) forControlEvents:UIControlEventTouchUpInside];
    
    }
    
    - (void)tapFig:(id)sender{
        //do something with self.timer
    
    }
    
    - (void) moveStickFig:(id)yourArgument{
        //Move the stick figure
        //A tophat and a cane might 
        //look nice on your stick figure
        // :-)
    }
    
    - (void)dealloc {
        [stickFig release];
        [timer release];
        [super dealloc];
    }
    
    
    @end
    

    Notice the @property declaration in the header file. I'd consider taking another look at the timer initialization too, but that could just be me. I hope this helps!

    0 讨论(0)
  • 2021-01-06 11:10

    You can create subclass of UIButton, add property in this subclass, store your object in this property and get it in action method through sender.

    0 讨论(0)
  • 2021-01-06 11:12

    You can't - UIControl action selectors are invoked with no parameters, the control that is the source of the action, or the control that is the source of the action and the UIEvent which occurred on that control. In IB you have to connect the UIButton to such a method: you can't add any other custom parameters.

    If you want it to have access to other objects, they need to be instance variables.

    Review Apple's Introduction to Objective C if you want to understand how to define instance variables.

    0 讨论(0)
  • 2021-01-06 11:18

    You could take the approach where you extend UIButton.

    @interface MyButton : UIButton
    @property (nonatomic, retain) NSDictionary *userInfo;
    @end
    

    Then your method

    - (void)foo:(MyButton *)sender{
        NSLog(@"%@", [sender.userInfo valueForKeyPath:@"extraData"]);
    }
    

    And to set userInfo

    ...
    MyButton *myButton = (MyButton *)[UIButton buttonWithType:UIButtonTypeCustom];
    //set up a dictionary with info, called userInfo
    myButton.userInfo = userInfo;
    [myButton addTarget:self selector:@selector(foo:) forControlEvent:UIControlEventTouchUpInside];
    

    Would that work for you?

    0 讨论(0)
  • 2021-01-06 11:23

    I suggest to create a small support class that works like a delegate that simply takes care of the click action for you, then change the target of your addTarget method.

    First create your support class:

    
    @interface ClickDelegate : NSObject {
        NSTimer timer;
    }
    
    @property (nonatomic, assign) NSTimer *timer;
    
    - (void)clickAction:(id)sender;
    
    @end
    
    
    @implementation ClickDelegate
    
    @synthesize timer; 
    
    - (void)clickAction:(id)sender {
        // do what you need (like destroy the NSTimer)
    }
    
    @end
    
    

    Then change the target:

    
    // In your view controller
                          
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:(0.009) target:self selector:@selector(moveStickFig:) userInfo:stickFig repeats:YES];                                                                               
       
    // Instantiate a new delegate for your delegate action
    // and set inside of it all the objects/params you need
    ClickDelegate *aDelegate = [[ClickDelegate alloc] init];
    aDelegate.timer = timer;
    
    [stickFig addTarget:aDelegate action:@selector(clickAction:) forControlEvents:UIControlEventTouchUpInside];
    
    self.myDelegate = aDelegate; // as suggested in the comments, you need to retain it
    [aDelegate release]; // and then release it
    
    

    In this way you're delegating the click callback to another object. This case is really simple (you just need to get the NSTimer instance) but in a complex scenario it also helps you to design the application logic by delegating different stuff to different small classes.

    Hope this helps! Ciao

    0 讨论(0)
提交回复
热议问题