setNeedsLayout是如何工作的?

4
我想了解苹果的-setNeedsLayout是如何工作的。
我已经知道它比直接调用-layoutSubviews更有效率,因为在某些情况下我可能需要在一个方法中调用两次。
这正是我所需要的:为视图控制器实现一些自定义的-setNeedsValidation功能。
但是如何实现这样的特性呢?
2个回答

5

我无法确定苹果公司是否确切地以这种方式执行此操作,但以下是一种实现您所需功能的方法,可能类似于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
}

1

只是随便想想...文档说-setNeedsLayout会在下一个“更新周期”(或者在-layoutSubviews文档中提到的“绘制更新”)中安排布局更新。

所以-setNeedsLayout很可能设置了一个BOOL标志。稍后检查该标志(在-drawRect:中?),如果设置为YES,则调用-layoutSubviews。然后清除该标志并等待下一次调用-setNeedsLayout


这正是我所想的。那么,我该如何创建一个在下一次主运行循环中执行的方法? - Christian Schnorr
使用-performSelector:withObject:afterDelay:方法并将延迟参数设置为零时,会立即将选择器执行计划到运行循环中。 - ayoy
好的,那很明显。抱歉。 - Christian Schnorr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接