Patrick
Patrick

Reputation: 252

passing arguments by a button's tag in objective-c

I saw someone passing arguments by a button's tag as follow. how could this work? and is it safe to do like this ?

NSCustomClass* cls = [[NSCustomClass alloc] init:@"",@"",@""];
[button setTag:(int) cls];



- (void)OnClick:(id)sender
{
    NSCustomClass* cls = (NSCustomClass*)[sender tag];
    // to do something with the "cls".
    [cls release];
}

In fact,I didn't get weird results.

It works fine by passing arguments like 'NSString','NSArray' in this way.

Can you tell me why it is a bad idea?

Upvotes: 0

Views: 256

Answers (4)

Conrad Shultz
Conrad Shultz

Reputation: 8808

In general you never want to abuse the frameworks. The tag is intended to store an integer and is used mainly to access a view with viewWithTag:, which can be useful in some cases if your view was built in Interface Builder but a referencing IBOutlet is inappropriate. Stuffing a pointer into an int can give unpredictable results, as others have indicated.

On top of that there's a memory management issue. Even if the pointer survives the cast you aren't retaining the object being pointed to. This in effect is a weak pointer but without any management by the run-time. Attempts to use the pointer will likely lead to the dreaded EXC_BAD_ACCESS. And who knows what ARC might do with this mess - blow up, I would expect.

To attach data to a button (which in and of itself sounds like a possible design flaw) you should either subclass or leverage the power of the run-time with objc_setAssociatedObject() and friends.

Upvotes: 1

UmbalaAZ
UmbalaAZ

Reputation: 165

You could subclass from UIButton and define a property by yourself, instead of using its tag property.

Upvotes: 0

dreamlax
dreamlax

Reputation: 95315

In general, casting from a pointer type to an integer type usually indicates a design flaw; there are very few legitimate reasons to do this, and I would strongly discourage doing it, especially in this case. It may work, but it's not guaranteed to work, simply because the tag property is not documented to be used this way. The more “hacks” that you put in your code, the harder it is to maintain.

Don't learn from the code where you saw this, instead stick to reputable tutorials and books.

As a side note, it is conventional in Objective-C to name all methods starting with a lowercase letter, so the method should be onClick: and not OnClick:. The exception to this rule is when the method starts with an acronym, for example -[NSString UTF8String].

Upvotes: 1

FeifanZ
FeifanZ

Reputation: 16316

Casting a custom class to an int is a very bad idea and you'll get weird results.

The tag is an integer property on all UI elements. It is declared as such on UIView:

@property(nonatomic) NSInteger tag;

You can assign any integer value to it, including any predefined constants:

#define Button1Constant 1
#define PushButtonConstant 2
// …Code
[button setTag:PushButtonConstant];
// …More code
if (sender.tag == PushButtonContent)
    // Handle

Upvotes: 2

Related Questions