SetNeedsLayout

本文对比分析了 UIView 和 CALayer 中 setNeedsLayout 方法的作用及其实现原理,详细介绍了如何通过该方法来触发视图和图层的子元素布局更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个方法和SetNeedsDisplay非常相似,并且也是CALayer 和 UIView都有的同名方法,我们在上篇认识了:layoutSubViews 这个方法,对应的,层Layer拥有layoutSublayers的相似方法。根据文档:


“发动触发在下一个更新循环中更新布局,在主线程中调用,并集中在同一个更新周期,旨在提高性能“ 

和SetNeedsDisplay方法一样,这个方法也是专门为layoutSubViews服务的。

UIView

头文件:

#import <UIKit/UIKit.h>

@interface LBSetNeedsLayoutViewController : UIViewController

@end

#pragma mark - LBSetNeedsLayoutView

@interface LBSetNeedsLayoutView : UIView

@property (nonatomic, assign) BOOL isChangeTheBackgroundColor;

@end

实现文件:

#import "UIColor+RandomColor.h"
#import "LBSetNeedsLayoutViewController.h"

@interface LBSetNeedsLayoutViewController ()

@property (nonatomic, strong) LBSetNeedsLayoutView* setNeedsLayoutView;

@end

@implementation LBSetNeedsLayoutViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.setNeedsLayoutView = [[LBSetNeedsLayoutView alloc] init];
    [self.setNeedsLayoutView setFrame:CGRectMake(0, 0, 100, 100)];
    [self.setNeedsLayoutView setBackgroundColor:[UIColor randomColor]];
    [self.view addSubview:self.setNeedsLayoutView];
    
    UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setFrame:CGRectMake(0, 0, 50, 50)];
    [button setCenter:CGPointMake(self.view.center.x, button.center.y + 50)];
    [button setBackgroundColor:[UIColor blueColor]];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}


- (void)buttonClicked:(id)sender
{
    [self.setNeedsLayoutView setIsChangeTheBackgroundColor:YES];
    
    [self.setNeedsLayoutView setNeedsLayout];
}

 @end


#pragma mark - LBSetNeedsLayoutView


@implementation LBSetNeedsLayoutView

- (id)init
{
    self = [super init];
    
    if (self)
    {
        _isChangeTheBackgroundColor = NO;
    }
    
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    
    if (_isChangeTheBackgroundColor)
    {
        [self setBackgroundColor:[UIColor randomColor]];
    }
    
    NSLog(@" Test setNeedsLayout RelationShip.. ");
}

@end


CALayer

头文件:

#import <UIKit/UIKit.h>

@interface LBSetNeedsLayoutLayerController : UIViewController

@end

#pragma mark - LBSetNeedsLayoutLayer

@interface LBSetNeedsLayoutLayer : CALayer

@property (nonatomic, assign) BOOL isChangeTheBackgroundColor;

@end

实现文件:

#import "UIColor+RandomColor.h"
#import "LBSetNeedsLayoutLayerController.h"

@interface LBSetNeedsLayoutLayerController ()

@property (nonatomic, strong) LBSetNeedsLayoutLayer* setNeedsLayoutLayer;

@end

@implementation LBSetNeedsLayoutLayerController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.setNeedsLayoutLayer = [LBSetNeedsLayoutLayer layer];
    [self.setNeedsLayoutLayer setBackgroundColor:[UIColor randomColor].CGColor];
    [self.setNeedsLayoutLayer setBounds:CGRectMake(0, 0, 150, 150)];
    [self.view.layer addSublayer:self.setNeedsLayoutLayer];
    
    
    UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setFrame:CGRectMake(0, 0, 50, 50)];
    [button setCenter:CGPointMake(self.view.center.x, self.view.center.y)];
    [button setBackgroundColor:[UIColor yellowColor]];
    [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}

- (void)buttonClicked:(id)sender
{
    [self.setNeedsLayoutLayer setIsChangeTheBackgroundColor:YES];
    
    [self.setNeedsLayoutLayer setNeedsLayout];
}

@end


#pragma mark - LBSetNeedsLayoutLayer

@implementation LBSetNeedsLayoutLayer

- (void)layoutSublayers
{
    [super layoutSublayers];
    
    if (_isChangeTheBackgroundColor)
    {
        [self setBackgroundColor:[UIColor randomColor].CGColor];
    }
    
    NSLog(@"setNeedsLayout invokes layoutSublayers");
}

@end


有些人会疑问,那这两者究竟区别是什么呢?其实很显然了,一个是视图重绘,一个是针对子视图的布局更新


http://stackoverflow.com/questions/14506968/setneedslayout-and-setneedsdisplay



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值