Перерисовка UIControls / UIButtons на iPhone в примере кода BubbleLevel - PullRequest
2 голосов
/ 08 сентября 2010

Я не совсем понимаю, когда я должен вызывать -setNeedsDisplay. В качестве примера, для обновления кнопки с разными изображениями между нажатиями (переключение между двумя), пример кода от Apple показывает -setImage, вызываемый на UIButton. Там нет вызова для -setNeedsDisplay, который я могу найти после этого, хотя. Так все ли методы UIControl выполняют внутренне -setNeedsDisplay, и, таким образом, -setNeedsDisplay можно использовать только при манипулировании экземплярами UIView? Или есть более конкретная семантика? Если я подкласс UIView, должны ли мои методы всегда обрабатывать перерисовку внутри? Как / где это указано в документации?

С LevelView.m в исходном коде BubbleLevel:

- (void)toggleHoldButton:(id)sender {
    if (holdButtonIsShowing == YES) 
    {
        holdButtonIsShowing = NO;
        [holdButton setImage:[UIImage imageNamed:@"release_button.png"] forState:UIControlStateNormal];
    } else 
    {
        holdButtonIsShowing = YES;
        [holdButton setImage:[UIImage imageNamed:@"hold_button.png"] forState:UIControlStateNormal];
    }    
}

1 Ответ

1 голос
/ 08 сентября 2010

setNeedsDisplay используется для повторного рендеринга или перерисовки представления (экземпляр подкласса UIView или UIView).С нашей точки зрения: он вызывает drawRect: но на самом деле до этого он подготавливает контекст и готовит представление для повторного рисования.(Вот почему вы не должны вызывать drawRect: напрямую)

Обычный случай, когда вы реализовали метод drawRect: (некоторые примеры: рисование содержимого с помощью OpenGL в виде или рисование текста с использованием CoreText или рисование некоторой графикииспользование CoreGraphics и т. д.) если вы хотите явно обновить чертеж в определенный момент, вы вызываете setNeedsDisplay, и он вызывает drawRect: и ваше представление будет перерисовано сразу.Если нет, метод drawRect: будет вызван, когда границы представления изменились, и в некоторых других ситуациях, когда система решит, что необходимо перерисовать представление.

В случае кнопки вы ненужно сделать это, потому что, конечно, когда кнопка нажата, внутренний вызов setNeedsDisplay будет сделан, чтобы кнопка изменилась и т. д. (Кто действительно знает, что происходит в фоновом режиме. Дело в том, что вам не нужно беспокоиться о drawRect:при использовании кнопок UIB таким способом)

Вы также можете изменить внешний вид представления, перемещая его подслои или подпредставления, что не обязательно означает перерисовку представления.Это тот случай, когда вы просматриваете себя как контейнер, а не как объект рисования.

Хорошим правилом может быть то, что вам не нужно явно вызывать setNeedsDisplay, если вы не реализовали drawRect: метод.

http://developer.apple.com/iphone/library/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/drawRect:

Надеюсь, это поможет.

;)

ОБНОВЛЕНИЕ: 2009/09/09

способ, которым UIButton вызывает drawRect: зависит от его реализации, и мы должны заботиться об этом (по крайней мере, если мы не подклассы).Но если вы действительно знаете это, вы можете создать его подкласс и переопределить:

- (void) drawRect:(CGRect)frame{
    NSLog(@"%s is being called!!!", _cmd);
    [super drawRect:frame];
}

и теперь из другого объекта попробуйте загрузить его, изменить его размер, переместить, прокрутить (если доступно), скрыть и увидеть отладку.console (Cmd + Shift + R) Я бы порекомендовал сделать это не только для UIButton, но и для обычного UIView.Это, безусловно, даст ясную идею, когда drawRect: вызывается.;) (Также другие методы, такие как layoutSubviews: и т. Д.)

Причина, по которой я сказал, что мы не должны заботиться о drawRect: в UIButton, потому что он нам не нужен, мы предварительно устанавливаем изображение для определенного состоянияиспользуя setImage: forState: и это все.Мы можем переустановить эти изображения в любое время, и кнопка изменит свое изображение по мере необходимости, и она может перерисовать свой вид в зависимости от того, как разработчики Apple его спроектировали.

Относительно вашего вопроса, если setNeedsDisplay соответствует правилу, которое я дал вам,Я верю даЯ поставил точку останова в начале каждого метода и ничего и проверил, что произошло при вызове setNeedsDisplay.Ни один из методов LeverView не был вызван!Затем я прокомментировал 3 вызова setNeedsDisplay, и результаты были одинаковыми!(iOS4.1) Следовательно, эти три строки кода не нужны.;)

Вы должны быть осторожны при вызове setNeedsDisplay, потому что в зависимости от вашей реализации это может сделать вашу программу очень медленной!так как собирается перерисовать все и, вероятно, не нужно.;)

Фууу ... лол.Довольно длинный пост только про drawRect:

Cheers

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...