#objective-c #delay #setter #nsrunloop #delayed-execution
#objective-c #задержка #установщик #nsrunloop #отложенное выполнение
Вопрос:
Я хотел бы знать, как -setNeedsLayout
работает Apple.
Я уже знаю, что это более эффективно, чем прямой вызов -layoutSubviews
, поскольку мне может потребоваться сделать это дважды в методе.
И это именно то, для чего мне это нужно: некоторые настройки -setNeedsValidation
для контроллера представления.
Но как реализовать такую функцию?
Ответ №1:
Я не могу подтвердить, что Apple делает это именно так, но вот способ сделать то, что вы ищете, и, вероятно, похож на то, как setNeedsLayout
это реализовано. Я не тестировал это (или даже не компилировал его), но это должно дать представление о том, как атаковать проблему как категорию UIViewController
. Как и UIKit, это полностью небезопасно для потоков.
static NSMutableSet sViewControllersNeedingValidation = nil;
static BOOL sWillValidate = NO;
@implementation UIViewController (Validation)
(void)load {
sViewControllersNeedingValidation = [[NSMutableSet alloc] init];
}
- (void)setNeedsValidation {
[sViewControllersNeedingValidation addObject:self];
if (! sWillValidate) {
sWillValidate = YES;
// Schedule for the next event loop
[[self class] performSelector:@selector(dispatchValidation) withObject:nil afterDelay:0];
}
}
(void)dispatchValidation {
sWillValidate = NO;
// The copy here is in case any of the validations call setNeedsValidation.
NSSet *controllers = [sViewControllersNeedingValidation copy];
[sViewControllersNeedingValidation removeAllObjects];
[controllers makeObjectsPerformSelector:@selector(validate)];
[controllers release];
}
- (void)validate {
// Empty default implementation
}
Ответ №2:
Просто размышляю вслух… В документации говорится, что -setNeedsLayout
обновление макета планируется в следующем «цикле обновления» (или «обновлении чертежа», как указано в -layoutSubviews
документах).
Поэтому -setNeedsLayout
, скорее всего, устанавливает BOOL
флаг. Флаг проверяется позже (в -drawRect:
?) и, если он установлен YES
, -layoutSubviews
вызывается. Затем флаг сбрасывается и ожидает следующих вызовов -setNeedsLayout
.
Комментарии:
1. Это именно то, что я подумал. Итак, как мне создать метод, который будет выполняться на следующей итерации основного цикла выполнения?
2.
-performSelector:withObject:afterDelay:
с нулевой задержкой планирует выполнение селектора в цикле выполнения.3. Хорошо, это было очевидно. Извините.