Home asdisplaynode-extras
Post
Cancel

asdisplaynode-extras

ASDisplayNodeExtras.mm

ASDisplayNodePerformBlockOnEveryNode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void ASDisplayNodePerformBlockOnEveryNode(CALayer * _Nullable layer, ASDisplayNode * _Nullable node, BOOL traverseSublayers, void(^block)(ASDisplayNode *node))
{
  if (!node) {
    ASDisplayNodeCAssertNotNil(layer, @"Cannot recursively perform with nil node and nil layer");
    ASDisplayNodeCAssertMainThread();
    node = ASLayerToDisplayNode(layer);
  }
  
  if (node) {
    block(node);
  }
  if (traverseSublayers && !layer && [node isNodeLoaded] && ASDisplayNodeThreadIsMain()) {
    layer = node.layer;
  }
  
  if (traverseSublayers && layer && node.rasterizesSubtree == NO) {
    /// NOTE: The docs say `sublayers` returns a copy, but it does not.
    /// See: http://stackoverflow.com/questions/14854480/collection-calayerarray-0x1ed8faa0-was-mutated-while-being-enumerated
    for (CALayer *sublayer in [[layer sublayers] copy]) {
      ASDisplayNodePerformBlockOnEveryNode(sublayer, nil, traverseSublayers, block);
    }
  } else if (node) {
    for (ASDisplayNode *subnode in [node subnodes]) {
      ASDisplayNodePerformBlockOnEveryNode(nil, subnode, traverseSublayers, block);
    }
  }
}

ASDisplayNodePerformBlockOnEveryNodeBFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void ASDisplayNodePerformBlockOnEveryNodeBFS(ASDisplayNode *node, void(^block)(ASDisplayNode *node))
{
  // Queue used to keep track of subnodes while traversing this layout in a BFS fashion.
  std::queue<ASDisplayNode *> queue;
  queue.push(node);
  
  while (!queue.empty()) {
    node = queue.front();
    queue.pop();
    
    block(node);

    // Add all subnodes to process in next step
    for (ASDisplayNode *subnode in node.subnodes) {
      queue.push(subnode);
    }
  }
}

ASDisplayNodePerformBlockOnEverySubnode

1
2
3
4
5
6
void ASDisplayNodePerformBlockOnEverySubnode(ASDisplayNode *node, BOOL traverseSublayers, void(^block)(ASDisplayNode *node))
{
  for (ASDisplayNode *subnode in node.subnodes) {
    ASDisplayNodePerformBlockOnEveryNode(nil, subnode, YES, block);
  }
}

ASDisplayNodeFindFirstSupernode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
ASDisplayNode *ASDisplayNodeFindFirstSupernode(ASDisplayNode *node, BOOL (^block)(ASDisplayNode *node))
{
  // This function has historically started with `self` but the name suggests
  // that it wouldn't. Perhaps we should change the behavior.
  for (ASDisplayNode *ancestor in node.supernodesIncludingSelf) {
    if (block(ancestor)) {
      return ancestor;
    }
  }
  return nil;
}

__kindof ASDisplayNode *ASDisplayNodeFindFirstSupernodeOfClass(ASDisplayNode *start, Class c)
{
  // This function has historically started with `self` but the name suggests
  // that it wouldn't. Perhaps we should change the behavior.
  return [start supernodeOfClass:c includingSelf:YES];
}

static void _ASCollectDisplayNodes(NSMutableArray *array, CALayer *layer)
{
  ASDisplayNode *node = ASLayerToDisplayNode(layer);

  if (nil != node) {
    [array addObject:node];
  }

  for (CALayer *sublayer in layer.sublayers)
    _ASCollectDisplayNodes(array, sublayer);
}

ASDisplayNodeFindFirstSupernodeOfClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__kindof ASDisplayNode *ASDisplayNodeFindFirstSupernodeOfClass(ASDisplayNode *start, Class c)
{
  // This function has historically started with `self` but the name suggests
  // that it wouldn't. Perhaps we should change the behavior.
  return [start supernodeOfClass:c includingSelf:YES];
}

static void _ASCollectDisplayNodes(NSMutableArray *array, CALayer *layer)
{
  ASDisplayNode *node = ASLayerToDisplayNode(layer);

  if (nil != node) {
    [array addObject:node];
  }

  for (CALayer *sublayer in layer.sublayers)
    _ASCollectDisplayNodes(array, sublayer);
}

_ASCollectDisplayNodes

1
2
3
4
5
6
7
8
9
10
11
static void _ASCollectDisplayNodes(NSMutableArray *array, CALayer *layer)
{
  ASDisplayNode *node = ASLayerToDisplayNode(layer);

  if (nil != node) {
    [array addObject:node];
  }

  for (CALayer *sublayer in layer.sublayers)
    _ASCollectDisplayNodes(array, sublayer);
}

ASCollectDisplayNodes

1
2
3
4
5
6
7
8
NSArray<ASDisplayNode *> *ASCollectDisplayNodes(ASDisplayNode *node)
{
  NSMutableArray *list = [[NSMutableArray alloc] init];
  for (CALayer *sublayer in node.layer.sublayers) {
    _ASCollectDisplayNodes(list, sublayer);
  }
  return list;
}

_ASDisplayNodeFindAllSubnodes

1
2
3
4
5
6
7
8
9
10
11
12
13
static void _ASDisplayNodeFindAllSubnodes(NSMutableArray *array, ASDisplayNode *node, BOOL (^block)(ASDisplayNode *node))
{
  if (!node)
    return;

  for (ASDisplayNode *subnode in node.subnodes) {
    if (block(subnode)) {
      [array addObject:subnode];
    }

    _ASDisplayNodeFindAllSubnodes(array, subnode, block);
  }
}

ASFindWindowOfLayer

1
2
3
4
5
6
7
8
9
UIWindow * _Nullable ASFindWindowOfLayer(CALayer *layer)
{
  UIView *view = ASFindClosestViewOfLayer(layer);
  if (UIWindow *window = ASDynamicCast(view, UIWindow)) {
    return window;
  } else {
    return view.window;
  }
}

ASFindClosestViewOfLayer

1
2
3
4
5
6
7
8
9
10
UIView * _Nullable ASFindClosestViewOfLayer(CALayer *layer)
{
  while (layer != nil) {
    if (UIView *view = ASDynamicCast(layer.delegate, UIView)) {
      return view;
    }
    layer = layer.superlayer;
  }
  return nil;
}

ASDisplayNodeFindClosestCommonAncestor

1
2
3
4
5
6
7
8
9
10
11
12
13
ASDisplayNode *ASDisplayNodeFindClosestCommonAncestor(ASDisplayNode *node1, ASDisplayNode *node2)
{
  ASDisplayNode *possibleAncestor = node1;
  while (possibleAncestor) {
    if (_ASDisplayNodeIsAncestorOfDisplayNode(possibleAncestor, node2)) {
      break;
    }
    possibleAncestor = possibleAncestor.supernode;
  }
  
  ASDisplayNodeCAssertNotNil(possibleAncestor, @"Could not find a common ancestor between node1: %@ and node2: %@", node1, node2);
  return possibleAncestor;
}

ASDisplayNodeUltimateParentOfNode

1
2
3
4
5
6
7
8
9
10
11
ASDisplayNode *ASDisplayNodeUltimateParentOfNode(ASDisplayNode *node)
{
  // node <- supernode on each loop
  // previous <- node on each loop where node is not nil
  // previous is the final non-nil value of supernode, i.e. the root node
  ASDisplayNode *previousNode = node;
  while ((node = [node supernode])) {
    previousNode = node;
  }
  return previousNode;
}

ASDisplayNodeDefaultPlaceholderColor

1
2
3
4
5
6
7
8
9
10
UIColor *ASDisplayNodeDefaultPlaceholderColor()
{
  static UIColor *defaultPlaceholderColor;

  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    defaultPlaceholderColor = [UIColor colorWithWhite:0.95 alpha:1.0];
  });
  return defaultPlaceholderColor;
}

ASDisplayNodeDefaultTintColor

1
2
3
4
5
6
7
8
9
10
UIColor *ASDisplayNodeDefaultTintColor()
{
  static UIColor *defaultTintColor;

  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    defaultTintColor = [UIColor colorWithRed:0.0 green:0.478 blue:1.0 alpha:1.0];
  });
  return defaultTintColor;
}

ASDisplayNodeDisableHierarchyNotifications

void ASDisplayNodeDisableHierarchyNotifications(ASDisplayNode *node)
{
  [node __incrementVisibilityNotificationsDisabled];
}

ASDisplayNodeEnableHierarchyNotifications

1
2
3
4
void ASDisplayNodeEnableHierarchyNotifications(ASDisplayNode *node)
{
  [node __decrementVisibilityNotificationsDisabled];
}
This post is licensed under CC BY 4.0 by the author.