setNeedsLayout如何工作?

时间:2011-10-17 13:06:14

标签: objective-c delay setter nsrunloop delayed-execution

我想知道Apple的-setNeedsLayout是如何运作的。

我已经知道它比直接调用-layoutSubviews更有效率,因为我可能需要在方法中执行两次。
这正是我所需要的:视图控制器的一些自定义-setNeedsValidation 但是如何实现这样的功能?

2 个答案:

答案 0 :(得分:5)

我无法确认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
}

答案 1 :(得分:1)

大声思考......文档说明-setNeedsLayout会在下一个“更新周期”(或“图纸更新”中安排布局更新,如-layoutSubviews文档中所述)。

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