Objective c Comparison NSString
I have three buttons named (named) hello, nothing, sky and one label (IBOutlet UIlabel). I want to display three diff messages for three diff button clicks. But the following code failed to accomplish this. Can anyone suggest any idea?
-(IBAction)buttonclick:(id)sender
{
NSString *title=[sender titleForState:UIControlStateNormal];
if([title isEqualToString:@"hello"])
{
NSString *str=[[NSString alloc] initWithFormat:@"abc"];
}
else if([title isEqualToString:@"nothing"]) {
NSString *str=[[NSString alloc] initWithFormat:@"def"];
}
else if([title isEqualToString:@"heaven"])
{
NSString *str=[[NSString alloc] initWithFormat:@"ijk"];
}
lab.text=str;
[str release];
}
output:
warning:unused variable str;
source to share
The problem is that in each "then" clause of various statements, if
you create a new local variable with a name str
, assigning it to a new line, and then the variable is out of scope. A compiler warning should flag you like this: You write a variable, but you don't read it.
Typically, your code will not compile, but another variable named will appear in the visible scope later str
. Your new definitions str
obscure the old one: while the new name str
is in scope, the name str
refers to that variable, not the external one, and the external cannot be referenced.
The solution is to move the declaration to the str
top of the function. Also, it's easier to use [NSString stringWithFormat:@"blah"]
instead [[NSString alloc] initWithFormat:@"blah"]
, since the former gives you an auto-implemented object. This saves you the hassle of manually release
later. Note that the assignment lab.text=str
preserves it because the text
class property UILabel
has a modifier retain
.
-(IBAction)buttonclick:(id)sender
{
NSString *title=[sender titleForState:UIControlStateNormal];
NSString *str;
if([title isEqualToString:@"hello"])
{
str=[NSString stringWithFormat:@"abc"];
}
else if([title isEqualToString:@"nothing"])
{
str=[NSString stringWithFormat:@"def"];
}
else if([title isEqualToString:@"heaven"])
{
str=[NSString stringWithFormat:@"ijk"];
}
lab.text=str;
}
Also note that with the original code you had both a memory leak and memory corruption - as you allocated a string and then lost a reference to it (with a new local variable str
out of scope) without freeing it, and then you took release
extra time for any external variable str
. Moving the declaration str
to the top of the function fixes both problems.
I also assume that your formatted strings are more complex than plain strings. If you are actually assigning constant strings like "abc"
, then of course it is much easier to just str=@"abc"
instead str=[NSString stringWithFormat:@"abc"]
.
source to share
Don't use the title of the buttons to differentiate your buttons. It won't work if your buttons are localized. Either use different actions or use a tag to distinguish them.
Warning is the key to what you are doing wrong in this case. The local variable is only visible within the scope it has declared, so your lab.text = str line actually sets lab.text for str that is defined elsewhere, either a static variable or an instance variable. Here's what you could do instead:
NSString *str;
switch ([sender tag]) {
case FirstButtonTag:
str = @"abc";
break;
case SecondButtonTag:
str = @"def";
break;
case ThirdButtonTag:
str = @"ijk";
break;
}
lab.text = str;
source to share