iOS:转储视图和约束的层次结构树

时间:2016-11-14 11:37:48

标签: ios autolayout ios-autolayout

在iOS中调试自动布局可能非常烦人。我们正在寻找一种方法来转储子视图及其约束,以便更好地进行调试。

使用调试器获取一些信息有两种有用的方法:

  • 转储视图树:po [[UIWindow keyWindow] recursiveDescription]
  • 追踪约束:po [[UIWindow keyWindow] _autolayoutTrace];

StackOverflow中有几个答案,其中有关于转储视图但没有相应约束的想法。有没有一种有用的方法呢?

1 个答案:

答案 0 :(得分:0)

以下函数可用于视图及其相应的自动布局约束的树的良好转储:

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);
}

输出如下:

.<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>