简体   繁体   中英

iOS: Dumping hierarchy tree of views and constraints

Debugging of auto-layout in iOS can be quite annoying. We are looking for a way to dump the subviews and their constraints in a way that will allow a better debugging.

There are two useful ways to use the debugger to get some info:

  • Dumping the views tree: po [[UIWindow keyWindow] recursiveDescription]
  • Tracing constraints: po [[UIWindow keyWindow] _autolayoutTrace];

There are several answers in StackOverflow with ideas for dumping the views but without their corresponding constraints . Is there a useful way to do it?

The following function can be used for a nice dump of the tree for both the views and their corresponding auto-layout constraints:

void dumpViewRecursivelyWithConstraints(UIView *vw, NSString *title)
{
    if (!vw) {
        vw = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
    }
    void (^dumpViewRecursively)(UIView*, NSString*, NSMutableString*); //local var definition
    void (^ __block __weak weakDumpViewRecursively)(UIView*, NSString*, NSMutableString*); //weak copy for recursion
    weakDumpViewRecursively = dumpViewRecursively = ^void(UIView *vw, NSString* gap, NSMutableString *mStr) {
        [mStr appendFormat:@"%@.%@\n", gap, vw];
        for (NSLayoutConstraint *c in vw.constraints) {
            NSString *cStr = [NSString stringWithFormat:@"%@", c];
            NSInteger space = [cStr rangeOfString:@" "].location; //skipping up to space for a neater output
            [mStr appendFormat:@"%@| %@\n", gap, [cStr substringFromIndex:space+1]];
        }
        [mStr appendFormat:@"%@`----------------------------\n", gap];
        NSString *nextGap = [gap stringByAppendingString:@"      "];
        NSArray *subs = [vw subviews];
        for (int i=0; i<[subs count]; i++) {
            weakDumpViewRecursively(subs[i], nextGap, mStr); //call myself recursively
        }
    };
    NSMutableString *mStr = [[NSMutableString alloc] init];
    [mStr appendFormat:@"\n\n************** %@: **************\n", title];
    dumpViewRecursively(vw, @"", mStr);
    NSLog(@"%@", mStr);
}

The output looks like this:

.<UIView: 0x12c5bcb10; frame = (0 45; 1024 703); autoresize = W+H; gestureRecognizers = <NSArray: 0x12e436c70>; layer = <CALayer: 0x12c5b8580>>
| UIScrollView:0x12d176a00.width == UIView:0x12c5bcb10.width>
| UIScrollView:0x12d176a00.height == UIView:0x12c5bcb10.height>
| UIScrollView:0x12d176a00.centerX == UIView:0x12c5bcb10.centerX>
| UIScrollView:0x12d176a00.centerY == UIView:0x12c5bcb10.centerY>
| PlayerView:0x12c5bda20.width == UIView:0x12c5bcb10.width>
`----------------------------
    .<UIScrollView: 0x12d176a00; frame = (0 0; 1024 703); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x12e18b6e0>; layer = <CALayer: 0x12e054ec0>; contentOffset: {0, 0}; contentSize: {1848, 703}>
    | V:|-(0)-[UIView:0x12c5d1860]   (Names: '|':UIScrollView:0x12d176a00 )>
    | H:|-(0)-[UIView:0x12c5d1860](LTR)   (Names: '|':UIScrollView:0x12d176a00 )>
    | UIView:0x12c5d1860.height == UIScrollView:0x12d176a00.height>
    `----------------------------
          .<UIView: 0x12c5d1860; frame = (0 0; 1848 703); layer = <CALayer: 0x12c5ad540>>
          | H:[UIView:0x12c5d1860(1848)]>
          | H:|-(0)-[PlayerView:0x12c5bda20](LTR)   (Names: '|':UIView:0x12c5d1860 )>
          | V:|-(0)-[PlayerView:0x12c5bda20]   (Names: '|':UIView:0x12c5d1860 )>
          | PlayerView:0x12c5bda20.height == UIView:0x12c5d1860.height>
          | UIView:0x12e02bf50.top == UIView:0x12c5d1860.centerY - 10>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM