UIView:layoutSubviews vs initWithFrame

时间:2012-11-01 12:38:06

标签: ios uiview uiscrollview

在继承UIView时,我通常将所有初始化和布局代码放在init方法中。但我被告知布局代码应该通过覆盖layoutSuviews来完成。 SO上有一个post解释每个方法被调用时,但我想知道如何在实践中使用它们。

我目前将所有代码都放在init方法中,如下所示:

MyLongView.m

- (id)initWithHorizontalPlates:(int)theNumberOfPlates
{
    self = [super initWithFrame:CGRectMake(0, 0, 768, 1024)];

    if (self) {
        // Initialization code
        _numberOfPlates = theNumberOfPlates;

        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
        [scrollView setContentSize:CGSizeMake(self.bounds.size.width* _numberOfPlates, self.bounds.size.height)];
        [self addSubview:scrollView];

        for(int i = 0; i < _numberOfPlates; i++){
            UIImage *img = [UIImage imageNamed:[NSString stringWithFormat:@"a1greatnorth_normal_%d.jpg", i+1]];
            UIImageView *plateImage = [[UIImageView alloc] initWithImage:img];
            [scrollView addSubview:plateImage];
            plateImage.center = CGPointMake((plateImage.bounds.size.width/2) + plateImage.bounds.size.width*i, plateImage.bounds.size.height/2);
        }

    }
    return self;
}

通常的任务是:设置视图的框架,初始化ivar,设置滚动视图,初始化UIImages,将它们放在UIImageViews中,然后将它们放置出来。

我的问题是:哪些应该在init中完成,哪些应该在layoutSubviews中完成?

2 个答案:

答案 0 :(得分:15)

您的init应该使用所需的数据创建所有对象。你在init中传递给它们的任何帧理想地应该是它们的起始位置。

然后,在layoutSubviews:中,您可以更改所有元素的帧以将它们放置在应该去的位置。在layoutSubviews中不应该进行分配或初始化,只需更改其位置,大小等...

答案 1 :(得分:4)

如果你的自动调整功能与autoresizingFlags或autolayout完美配合,你可以只使用init来设置整个视图。

但总的来说,你应该在layoutSubviews中进行布局,因为这将在视图框架的每次更改时调用,而在其他情况下,需要再次布局。有时你只是不知道init中视图的最终帧,所以你需要像上面提到的那样灵活,或者使用layoutSubviews,因为你在设置了最终大小之后进行了布局。

如WDUK所述,所有初始化代码/对象创建都应该在init方法中或任何地方,但是layoutSubviews中的不是