一个接一个地放置UIViews

时间:2013-10-24 06:02:07

标签: ios iphone objective-c view

我有一个视图控制器,它有一个子视图数组。这些子视图是垂直放置的自定义UIViews。子视图的高度不一致;它们的高度基于实例化时使用的数据。另外,我想支持设备旋转,以便子视图的UILabel在横向模式下水平扩展并缩短。

我在很好地完成这项工作时遇到了很多麻烦。当视图控制器正在布置它的子视图时,我觉得我没有干净的方法来确定每个子视图的高度(因为我此时已经实例化了它们,但没有设置它们的帧)。请参考下面的代码来了解我的挫败感。

如果在视图控制器的 layoutSubviews 方法之前调用了子视图的 viewWillLayoutSubviews 方法,我真的很喜欢它事实并非如此。

MyViewController.m

....

- (void)initWithDataObjects:(NSArray*)dataObjects
{
    _dataObjects = dataObjects;
}

- (void)viewDidLoad
{
    mySubviews = [[NSMutableArray alloc] init];

    for (DataObject* do in _dataObjects) {
        MyCustomView *customView = [[MyCustomView alloc] initWithDataObject:do];
        [mySubviews addObject:customView];
        [self.view addSubview:customView];
    }
}

- (void)viewWillLayoutSubviews
{
    int currentHeight = 0;
    for (MyCustomView *customView in mySubviews) {

        int subviewHeight = customView.frame.size.height;
        // PROBLEM: subviewHeight is 0 because the subview hasn't called layoutSubviews yet..

        [customView setFrame:CGRectMake(0, currentHeight, self.view.frame.size.width, subviewHeight)];
        currentHeight += subviewHeight;
    }
}

1 个答案:

答案 0 :(得分:1)

我正在根据以下评论进行编辑和总结:

以下是调用这些方法的顺序:

2013-10-24 01:05:11.391 MyTestApp[34166:70b] -[MyViewController viewDidLoad]
2013-10-24 01:05:11.395 MyTestApp[34166:70b] -[MyViewController addMySubViews]
2013-10-24 01:05:11.395 MyTestApp[34166:70b] -[view1 didMoveToSuperview]
2013-10-24 01:05:11.395 MyTestApp[34166:70b] -[view2 didMoveToSuperview]
2013-10-24 01:05:11.395 MyTestApp[34166:70b] -[view3 didMoveToSuperview]
2013-10-24 01:05:11.398 MyTestApp[34166:70b] -[MyViewController viewWillLayoutSubviews]
2013-10-24 01:05:11.398 MyTestApp[34166:70b] -[MyViewController viewDidLayoutSubviews]
2013-10-24 01:05:11.398 MyTestApp[34166:70b] -[view1 layoutSubviews]
2013-10-24 01:05:11.398 MyTestApp[34166:70b] -[view2 layoutSubviews]
2013-10-24 01:05:11.398 MyTestApp[34166:70b] -[view3 layoutSubviews]

您最好的选择是从视图的layoutSubviews中取出您的大小调整代码,并将其放在单独的视图方法(可能是mySize)中,并从viewWillLayoutSubviews中的viewcontroller调用该方法,您也可以从视图的layoutSubviews中调用它(所以你没有重复的代码)。

这可能是它的样子(viewWillLayoutSubviews正在调用所有子视图的'mySize方法):

2013-10-24 01:38:10.501 MyTestApp[34850:70b] -[MyViewController viewDidLoad]
2013-10-24 01:38:10.501 MyTestApp[34850:70b] -[MyViewController addMySubViews]
2013-10-24 01:38:10.501 MyTestApp[34850:70b] -[view1 didMoveToSuperview]
2013-10-24 01:38:10.501 MyTestApp[34850:70b] -[view2 didMoveToSuperview]
2013-10-24 01:38:10.502 MyTestApp[34850:70b] -[view3 didMoveToSuperview]
2013-10-24 01:38:24.396 MyTestApp[34850:70b] -[MyViewController viewWillLayoutSubviews]
2013-10-24 01:38:24.396 MyTestApp[34850:70b] -[view1 mySize]
2013-10-24 01:38:24.396 MyTestApp[34850:70b] -[view2 mySize]
2013-10-24 01:38:24.396 MyTestApp[34850:70b] -[view3 mySize]
2013-10-24 01:38:24.397 MyTestApp[34850:70b] -[MyViewController viewDidLayoutSubviews]
2013-10-24 01:38:24.397 MyTestApp[34850:70b] -[view1 layoutSubviews]
2013-10-24 01:38:24.397 MyTestApp[34850:70b] -[view2 layoutSubviews]
2013-10-24 01:38:24.397 MyTestApp[34850:70b] -[view3 layoutSubviews]

顺便说一句,如果你从视图控制器中更改子视图的框架,它将在子视图上触发needsLayout,并最终触发layoutSubviews。