У меня есть три кнопки с названием (с заголовком) привет, ничего, небо и одна метка (лаборатория IBOutlet UIlabel). Я хочу отображать три сообщения о различиях для трех нажатий кнопки сравнения. Но следующий код не смог этого сделать. Кто-нибудь может предложить какую-нибудь идею?

-(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];
}

Выход:

warning:unused variable str;  
2
russell 9 Сен 2009 в 08:27

2 ответа

Лучший ответ

Проблема в том, что в каждом предложении 'then' различных операторов if вы создаете новую локальную переменную с именем str, назначаете ее новой строке, а затем переменная выходит за пределы области видимости. . Предупреждение компилятора должно указывать на это: вы пишете в переменную, но никогда не читаете ее.

Обычно ваш код не компилируется, но, по-видимому, позже в области видимости появится другая переменная с именем str. Ваши новые определения str затеняют старое: пока новое имя str находится в области видимости, имя str относится к этой переменной, а не к внешней один, а внешний не может быть упомянут.

Решение состоит в том, чтобы переместить объявление str в начало функции. Более того, проще использовать [NSString stringWithFormat:@"blah"] вместо [[NSString alloc] initWithFormat:@"blah"], поскольку первый дает вам автоматически выпускаемый объект. Это избавит вас от необходимости вручную release его позже. Обратите внимание, что назначение lab.text=str сохраняет его, поскольку свойство text класса UILabel имеет модификатор 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;
}

Также обратите внимание, что в исходном коде произошла как утечка памяти, так и повреждение памяти - поскольку вы выделяли строку, а затем теряли ссылку на нее (из-за того, что новая локальная переменная str выходит за пределы области видимости), не выпуская это, а затем вы вызывали release в дополнительное время независимо от того, какой была внешняя переменная str. Перемещение объявления str в начало функции устраняет обе проблемы.

Я также предполагаю, что ваши строки формата более сложны, чем простые строки. Если вы на самом деле назначаете постоянные строки, такие как "abc", то, конечно, гораздо проще просто сделать str=@"abc" вместо str=[NSString stringWithFormat:@"abc"].

3
Adam Rosenfield 9 Сен 2009 в 08:52

Не используйте названия кнопок, чтобы различать кнопки. Это не сработало бы, если бы ваши кнопки были локализованы. Либо используйте разные действия, либо используйте тег, чтобы различать их.

Предупреждение - это ключ к разгадке того, что вы делаете в данном случае не так. Локальная переменная видна только в той области видимости, в которой она объявлена, поэтому ваша строка lab.text = str фактически устанавливает lab.text в значение str, которое определено в другом месте, либо статической переменной, либо переменной экземпляра. Вот что вы могли бы сделать вместо этого:

NSString *str;

switch ([sender tag]) {
  case FirstButtonTag:
    str = @"abc";
    break;
  case SecondButtonTag:
    str = @"def";
    break;
  case ThirdButtonTag:
    str = @"ijk";
    break;
}

lab.text = str;
5
Chris Suter 9 Сен 2009 в 08:51