App is running properly, but not sure if (id)sender is needed in the button's action statement or not

StackOverflow https://stackoverflow.com/questions/20722900

Pergunta

My app is working just fine right now, but I don't understand why it is. It's a simple app with 1 button and 1 label. When the button is pressed, the label is populated with the users location coordinates.

Here is why I'm confused:

An hour ago, the app was not working properly. My button's action code looked like this in the header:

-(IBAction)gpsButton;

So I thought to myself that maybe I needed to change the action statement to this:

-(IBAction)gpsButton:(id)sender;

I made the change, made the new connection, and changed the action statement in my main file to include the new "(id)sender" as well.

Then, the app was working correctly! It looked like making that change had fixed everything.

However, I just went back and changed the action statement back to the original that was not working for me an hour ago, but for some reason now that is working too!

Keep in mind that both times I made any changes I deleted the app from iPhone, saved the project in xcode, and then ran it fresh on my iPhone.

So my question is, do I need to use A or B?

A:

-(IBAction)gpsButton;

B:

-(IBAction)gpsButton:(id)sender;

Don't get me wrong, I am very happy that my app is running properly now, but I don't understand why it is working for both A and B now, and which one I should actually be using and why. Can someone please clarify this for me and explain the theory behind the correct answer. Thank you.

Here is my ViewController.h code:

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>


@interface ViewController : UIViewController <CLLocationManagerDelegate>

@property (nonatomic, strong) IBOutlet UILabel * gpsLabel;
@property (nonatomic, strong) CLLocationManager * gpsLM;

-(IBAction)gpsButton;

@end

And here is my full ViewController.m code:

#import "ViewController.h" 
#import <CoreLocation/CoreLocation.h> 

@interface ViewController () <CLLocationManagerDelegate>

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray    *)locations;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.gpsLM = [[CLLocationManager alloc]init];

    [self.gpsLM startUpdatingLocation];

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];

}

-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{

    CLLocation * currentLocation = [locations lastObject];

    NSLog(@"%f", currentLocation.coordinate.latitude);

}

-(IBAction)gpsButton{

    CLLocation * currentLocation = self.gpsLM.location;

    self.gpsLabel.text = [NSString stringWithFormat:@"Your Location is %@", currentLocation];

}

@end
Foi útil?

Solução

It looked like making that change had fixed everything.

That was only a coincidence: the most likely problem is that the connection before you made the first change had been broken.

So my question is, do I need to use A (no sender) or B (with sender)?

The reason the sender parameter is there is to let you share the same code for handling clicks of multiple buttons. If you do not plan on sharing the event handler, use A; otherwise, use B.

Consider this example: let's say you need to implement code for handling a numeric pad. You could create ten handlers, one for each digit, to handle key presses, or you could wire all buttons to the same handler, give each button a different tag, and then use [sender tag] to pull the tag from the button inside your handler.

Outras dicas

in case B you can decide inside the action method, this with sender, from which button the message come. that makes sense if you have more than one button in your viewcontroller but you want allways the same action method called, but for different situations.

-(IBAction)gpsButton;

vs

-(IBAction)gpsButton:(id)sender;

So, if you're only ever hooking a single button up to the method and never calling it within code programmatically, you can always safely use the first format.

However... good practice probably calls for using the second format.

The second format takes an argument (id)sender. This is useful in many respects.

You can hook multiple buttons up to the same method and perform conditional logic based on which button was clicked by inspecting the sender argument.

But even if you only want a single button hooked up to this method, if you're calling the method programmatically, you can make use of the sender argument. It's type is id so you can pass it any argument you want. Typically when we call methods like this from code, we send it nil, to say "The button wasn't pressed, we're calling from code" essentially. But you send it an argument which your method will handle and this will work fine as long as the logic also handles the type of values that it will receive when the button is actually pressed.

When you assign -(IBAction)gpsButton; as a traget of a button, It's expecting -(IBAction)gpsButton; as target in your implementation file. It doesn't look for method overloads :). The same for -(IBAction)gpsButton:(id)sender; target. It's expecting -(IBAction)gpsButton:(id)sender; as target in your implementation file.

But prefered is (IBAction)gpsButton:(id)sender or (IBAction)gpsButton:(UIButton *)sender

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top