如果使用自动布局以编程方式创建 UIView 会延迟显示

Posted

技术标签:

【中文标题】如果使用自动布局以编程方式创建 UIView 会延迟显示【英文标题】:UIView Display Late If Creating It Programmatically with Auto Layout 【发布时间】:2016-04-07 13:56:00 【问题描述】:

我被困住了!我正在开发一个视图控制器,它将成为其他视图控制器的基础。其他人将从它延伸。

我想为 baseViewController 创建一些带有 编程约束 的视图(如自定义 NavigationBar),我创建了它。

所以我有故事板,有一个带有 rootViewController (HomeViewController) 的 navigationController,这个 homeViewController 是从 baseViewController 扩展而来的。

这是我的故事板的样子;

所以,我的约束正在起作用!但是使用编程约束创建的视图会在几秒钟后显示,这让我抓狂!

这是应用首次运行时的外观;

几秒钟后,我的视图出现了;

我还想分享我的代码。我正在使用视觉格式语言来创建约束;

- (void)viewDidLoad 
[super viewDidLoad];
[self initializeBaseView];
// Do any additional setup after loading the view.

- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark - Initialize BaseView

- (void)initializeBaseView

    //Background View
    if (self.backgroundContainerView == nil) 
        self.backgroundContainerView = [UIView new];
        self.backgroundContainerView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.view addSubview:self.backgroundContainerView];
        [self.view sendSubviewToBack:self.backgroundContainerView];
    
    [self initConstraint_1];


    //Navigation Header View
    if(self.navigationBarContainerView == nil)
        self.navigationBarContainerView = [UIView new];
        self.navigationBarContainerView.translatesAutoresizingMaskIntoConstraints = NO;
        [self.navigationBarContainerView setBackgroundColor:[UIColor clearColor]];
        [self.view addSubview:self.navigationBarContainerView];

    
    [self initConstraint_2];

    if (self.backgroundType==BackgroundTypeWhite) 
        //very light Gray
        [self.backgroundContainerView setBackgroundColor:APP_GRAY_COLOR_ATHENS];
    

    [self initializeBaseStyle];


- (void)initializeBaseStyle
    [self.navigationBarContainerView setBackgroundColor:[UIColor darkGrayColor]];




#pragma mark - Initialize Constraints

- (void)initConstraint_1
    // 1. Create a dictionary of views
    NSDictionary *viewsDictionary = @@"firstView":self.backgroundContainerView;
    NSDictionary *metrics = @@"vSpacing":@0, @"hSpacing":@0;

    // 2. Define the view Position and automatically the Size
    NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-vSpacing-[firstView]-hSpacing-|"
                                                                        options:0
                                                                        metrics:metrics
                                                                          views:viewsDictionary];

    NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-hSpacing-[firstView]-hSpacing-|"
                                                                        options:0
                                                                        metrics:metrics
                                                                          views:viewsDictionary];

    [self.view addConstraints:constraint_POS_V];
    [self.view addConstraints:constraint_POS_H];




- (void)initConstraint_2
    NSDictionary *viewsDictionary = @@"firstView": self.navigationBarContainerView, @"secondView": self.logoImage;
    NSDictionary *metrics = @@"vSpacing":@74,
                              @"hSpacing":@0,
                              @"BottomSpacing":@60,
                              @"firstViewHeight":@64
                              ;


    // 2. Define the view Position and automatically the Size (for the firstView)
    NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[firstView(firstViewHeight)]"
                                                                        options:0
                                                                        metrics:metrics
                                                                          views:viewsDictionary];

    NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-hSpacing-[firstView]-hSpacing-|"
                                                                        options:0
                                                                        metrics:metrics
                                                                          views:viewsDictionary];

    [self.view addConstraints:constraint_POS_V];
    [self.view addConstraints:constraint_POS_H];


我有很多问题;

可能是什么原因? 我可以在需要时使用情节提要吗 以编程方式创建约束? 我正在使用 viewDidLoad 来调用创建方法 查看和设置约束。 viewDidLoad 是个好地方吗? 此方案的最佳做法是什么? 如何像第一张图片一样立即初始化我的视图?

我希望这很清楚。 感谢您的回答,我期待收到您的来信。

【问题讨论】:

尝试在 viewDidAppear 中进行。 ViewDidload 不是处理视图和自动布局的正确位置 我不知道您的视图需要 2 秒才能显示的原因。我可以说的是,您的代码看起来非常复杂。两个建议:在情节提要而不是在代码中设置约束,因为它更容易。其次,导航控制器会自动为您提供导航栏,您不应该创建导航栏视图。见developer.apple.com/library/ios/documentation/UIKit/Reference/… P.S.您的应用看起来会很酷! 【参考方案1】:

如果不是强制性的,则首先从 IB 设置约束。如果必须,则在 viewDidAppear 和主线程中执行您的任务(如果需要)。

【讨论】:

如果你对自动布局有很好的了解,那么你在哪里给出约束并不重要。【参考方案2】:

在约束设置后调用setNeedsLayoutlayoutIfNeeded 方法。它会为你工作。

【讨论】:

不,它不起作用,理查德。几秒钟后它仍然出现。 @Richard G

以上是关于如果使用自动布局以编程方式创建 UIView 会延迟显示的主要内容,如果未能解决你的问题,请参考以下文章

使用自动布局约束以编程方式创建四个具有相同高度和宽度的 UIView

以编程方式在子类 UIView 的子视图上自动布局

UICollectionViewCell 以编程方式自动布局

如何以编程方式使用自动布局以编程方式添加 UIview?

使用自动布局的屏幕外 UIView(以编程方式)

如何使用自动布局在 ios 中以编程方式在 UIview 上添加 UIbutton