uikit——UIView——view hierarchy

view hierarchy

@property(nullable, nonatomic,readonly) UIView       *superview;
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;
@property(nullable, nonatomic,readonly) UIWindow     *window;

- (void)removeFromSuperview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
- (void)addSubview:(UIView *)view;
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;

- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;

- (BOOL)isDescendantOfView:(UIView *)view;  // returns YES for self.
解释:
  • view hierarchy本质是tree
  • superview:view parent
  • subviews:view children,添加subview会进行判断,nil不会添加,同一subview不会重复添加
  • window:view所在view hierarchy(tree) root,即view controller.view.superview

view hierarchy图层

  • superview位于下层,subviews位于上层
  • 同一subviews,索引小的位于下层,索引大的位于上层,索引也称为view z-index或z-order
- (void)drawView
{
    int width = self.view.bounds.size.width;
    int halfHeight = self.view.bounds.size.height / 2;
    
    {
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, halfHeight)];
        UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(40, 30, 200, 200)];
        UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(80, 60, 200, 200)];
        UIView *view1_1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 80, 80)];
        UIView *view1_2 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 80, 80)];
        
        view.backgroundColor = [UIColor purpleColor];
        view1.backgroundColor = [UIColor blueColor];
        view2.backgroundColor = [UIColor orangeColor];
        view1_1.backgroundColor = [UIColor redColor];
        view1_2.backgroundColor = [UIColor cyanColor];
        
        [self.view addSubview:view];
        [view addSubview:view1];
        [view addSubview:view2];
        [view1 addSubview:view1_1];
        [view1 addSubview:view1_2];
    }
    
    {
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, halfHeight, width, halfHeight)];
        UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(40, 30, 200, 200)];
        UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(80, 60, 200, 200)];
        UIView *view1_1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 80, 80)];
        UIView *view1_2 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 80, 80)];
        
        view.backgroundColor = [UIColor brownColor];
        view1.backgroundColor = [UIColor blueColor];
        view2.backgroundColor = [UIColor orangeColor];
        view1_1.backgroundColor = [UIColor redColor];
        view1_2.backgroundColor = [UIColor cyanColor];
        
        [self.view addSubview:view];
        [view addSubview:view2];
        [view addSubview:view1];
        [view1 addSubview:view1_1];
        [view1 addSubview:view1_2];
    }
}

view hierarchy遍历

view hierarchy指以receiver为root view hierarchy,view hierarchy先根遍历
通常情况下,遍历子树按从左到右顺利遍历(subview index从小到大),用代码表示:
- (void)traverse
{
    [self visit];
    
    for(int i = 0; i < self.subviews.count; ++i)
    {
        UIView *view = [self.subviews objectAtIndex:i];
        [view traverse];
    }
}
特殊情况下,为了性能优化,遍历子树按从右到左顺利遍历(subview index从大到小),用代码表示:
- (void)traverse
{
    [self visit];
    
    for(int i = self.subviews.count - 1; i >= 0; --i)
    {
        UIView *view = [self.subviews objectAtIndex:i];
        [view traverse];
    }
}
view的draw(layout)为了性能优化,遍历子树按从右到左顺利遍历(subview index从大到小),先draw(layout)上层图层,然后draw(layout)下层图层,如果下层图层区域被上层图层不透明覆盖,则不必draw(layout)这些区域,极大提高了draw(layout)性能

view hierarchy crash

view hierarchy本质为tree,因此切不可形成闭环(循环),一旦形成闭环(循环),就破坏tree结构,先根遍历无穷递归,crash
- (void)circleCrash
{
    UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 200)];
    UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
    UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    
    [self.view addSubview:view1];
    [self.view addSubview:view2];
    [view1 addSubview:subView];
    [subView addSubview:self.view];
}
self.view->view1->subview->self.view形成闭环(循环)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值