views:

1643

answers:

5

I have a IBAction such as:

- (IBAction)showPicker:(id)sender;

How can I get the name of the control from the sender variable?

I am typically a c# coder so have tried the following to no avail

senderName = ((UIButton *)sender).name;

I need something more descriptive than the control id (not the button title either). I have 5 buttons all calling the same method. I need to determine which was clicked in order to perform the methods actions on the appropriate control. I.E I have an address picker method but want to populate 5 text fields with different details with each of 5 buttons. Just trying to keep the code tidy

N.B Originally I was planning on using the Interface Builders name field, but I've been advised (below) that this isn't available at runtime.

+1  A: 

The name field under Interface Builder Identity is something unique to Interface Builder; I'm actually not sure exactly how it's used, but it doesn't map to a usable property, ivar or method on your actual control. Instead, use the tag property (under the View attributes) to differentiate different controls from an action method if you don't otherwise keep a reference to them as an ivar. If I'm misunderstanding you and you want the button's title, just use currentTitle instead.

Marc Charbonneau
thanks ok, updated question, where is the tag property
tigermain
Open the Inspector in IB, and in the first tab (Attributes) there will be a section at the bottom for View. You'll see the tag property there.
Marc Charbonneau
Thanks I found it where you said, shame it only accepts integers, but will do the task
tigermain
A: 

If the control has a name attribute, then:

NSString *senderName = [sender name];

This isn't something most controls have. You might want:

NSString *senderName = [sender title];

If it was an NSButton, for instance. Or as Marc says, for a UIButton, use currentTitle.

Matthew Schinckel
The button title isn't really appropriate (updated question)
tigermain
A: 

Try:

senderTitle = [sender currentTitle];
Abizern
updated question, the title isn't really appropriate, its a coding name I need not the visual name (updated question)
tigermain
No probs. Since you've added a comment, I won't delete the response.
Abizern
+4  A: 

You might want to look at using the tag property. It's an integer rather than a name, but can be used to differentiate between two controls. It's inherited from UIView so any control that's sending an event should have it.

It's editable in Interface Builder under View attributes.

It's a property so it can be accessed programatically with the dot notation:

control.tag

Or you can convert to a string as follows:

[stringWithFormat:@"%d", control.tag]
Stephen Darlington
where is this field I cannot find it interface builder, but sounds like it would do the trick
tigermain
I think it's in the "Identity" tab (far right) of the Attribute Inspector but I'll update the answer when I'm back in front of my Mac and can tell you for sure.
Stephen Darlington
Thanks thats where the name field is I was trying to use (but I cant see tag anywhere)
tigermain
Found it thanks to Marc, but Im getting the following error Program received signal: “EXC_BAD_ACCESS”. when I try doing the following NSLog((NSString *)[sender tag]);
tigermain
Tag is an integer field... by casting it to an NSString you are trying to access the memory at the address of whatever number you put in the tag field.
Lounges
This isn't want you really want. See my answer below; you should generally use outlets connected to your controls to reference them, and use a distinct action per control rather than comparing the sender of an action.
Chris Hanson
I set the tag in IB on UIButton but [sender tag] in IBAction returns 0, any idea why?
stefanB
+2  A: 

You don't use the name of an object in Interface Builder to refer to that object; it's just there for reference. (Interface Builder will also use it as a hint for what outlets connecting to the control and actions sent by the control might be named, but only as a hint.)

Instead, you add an outlet to a controller object that you connect to the object. This lets you access the object directly at runtime from your controller without going through any look-up step.

Also, it sounds like you have five buttons, with five things to do, all connected to the same action method. Don't do that.

In Cocoa and Cocoa Touch, you shouldn't typically create an action methods "per event" and then decide what to do based on which control sent the event. The controls in Cocoa handle events themselves, and translate them into higher-level actions. So you can implement five action methods in your controller, connect each button to its appropriate action method, and never have to decide what to do based on which control sent the action.

Obviously this isn't appropriate in all cases. For example, if you have a matrix of buttons with images that change at runtime, you would probably want them all to connect to the same action and distinguish them based on their tag property. A good rule of thumb is to use different action methods when dealing with "different" things, and use the same action method and control tags when dealing with "many of the same" thing.

Chris Hanson