Поменяйте UILabel в цикле - PullRequest
       2

Поменяйте UILabel в цикле

0 голосов
/ 18 февраля 2011

Я хочу изменить UILabel через 2 секунды в цикле. Но текущий код меняет его на последнее значение после завершения цикла.

- (IBAction) start:(id)sender{


   for (int i=0; i<3; i++) {
    NSString *tempStr = [[NSString alloc] initWithFormat:@"%s", @" "];

    int randomNumber = 1+ arc4random() %(3);

    if (randomNumber == 1) {
        tempStr = @"Red";
    }else if (randomNumber == 2) {
        tempStr = @"Blue";
    } else {
        tempStr = @"Green";
    }
       NSLog(@"log: %@ ", tempStr);
       labelsText.text = tempStr;
       [tempStr release];
        sleep(2);

    }
}

Ответы [ 3 ]

2 голосов
/ 18 февраля 2011

Ваш код обновляет метку до последнего значения только в том случае, если ваша функция блокирует основной поток, поэтому пользовательский интерфейс не может быть обновлен. Чтобы решить эту проблему, переместите ваш код обновления в отдельную функцию и вызовите его, используя метод performSelector:withObject:afterDelay:. (или запланировать звонки, используя NSTimer)

Возможное решение (вам также нужно разобраться со случаем, когда пользователь нажимает на вашу кнопку несколько раз подряд, но это не должно быть слишком сложно):

- (IBAction) start:(id)sender{
    [self updateLabel];
}

- (void) updateLabel{
   static const NSString* allStrings[] = {@"Red", @"Blue", @"Green"};
   static int count = 0;

   int randomNumber = arc4random()%3;
   NSString *tempStr = allStrings[randomNumber];

   NSLog(@"log: %@ ", tempStr);
   labelsText.text = tempStr;

   ++count;
   if (count)
      [self performSelector:@selector(updateLabel) withObject:nil afterDelay:2.0];

}
0 голосов
/ 18 февраля 2011

Не используйте sleep() для выполнения действий после задержки, это блокирует весь поток.Вместо этого используйте performSelector:withObject:afterDelay:.Поскольку вы, вероятно, выполняете это в главном потоке, sleep() будет блокировать любые обновления пользовательского интерфейса до тех пор, пока не завершится весь цикл, поэтому вы видите только последнее обновление.Как общее практическое правило, предположим, что пользовательский интерфейс никогда не обновляется, пока приложение не завершит выполнение вашего метода.

Не следует использовать %s в качестве спецификатора формата для NSStringэто спецификатор формата для строки C.Вы должны использовать %@ вместо этого.Фактически, если все, что вы делаете, это инициализируете строку с литералом NSString, вам вообще не нужно использовать initWithFormat, вы можете просто использовать сам литерал.

У вас также есть большойпроблемы с памятью.В начале цикла вы выделяете память для экземпляра NSString, который представляет собой один пробел.Затем вы перезаписываете указатель на эту память при повторном присвоении tempStr, что означает утечку исходного выделения памяти. Построить и проанализировать найдет подобные проблемы для вас.Затем вы отпускаете tempStr, но, поскольку второе присваивание этой переменной-указателю было автоматически выпущено NSString, экземпляр будет освобожден один раз слишком много, когда пул авто-выпуска истощается, что, вероятно, проявится как сбой, который невозможендля отладки чуть позже в приложении.

Я бы сделал что-то вроде этого:

- (void)showRandomColourAfterDelay {
    static NSUInteger count = 0;
    switch (arc4random()%3) {
        case 0:
            labelsText.text = @"Red";
        case 1:
            labelsText.text = @"Blue";
        case 2:
            labelsText.text = @"Green";
    }
    count++;
    if (count >= 3) return;
    [self performSelector:@selector(showRandomColourAfterDelay) withObject:nil afterDelay:3];
}

На самом деле, я бы, вероятно, использовал NSArray для хранения строк цвета,но это повлечет за собой изменения за пределами одного метода, поэтому я придерживаюсь вашего подхода жесткого программирования.

0 голосов
/ 18 февраля 2011
- (IBAction) start:(id)sender{
   for (int i=0; i<3; i++) {

    int randomNumber = 1+ arc4random() %(3);
    NSString *tempStr = @"";
    if (randomNumber == 1) {
        tempStr = @"Red";
    }else if (randomNumber == 2) {
        tempStr = @"Blue";
    } else {
        tempStr = @"Green";
    }
    [labelsText performSelector:@selector(setText:) withObject:tempStr afterDelay:i * 2]
       NSLog(@"log: %@ ", tempStr);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...