搞清楚initWithFrame:self.view.frame 20像素(状态栏)问题一劳永逸

时间:2011-11-11 20:52:27

标签: ios uiviewcontroller frame

我有一个简单的UINavigationController。在init方法中,我创建并添加UITableView作为子视图。

- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromCGRect(self.view.frame)); // {{0, 20}, {320, 460}}
        tableView = [[UITableView alloc] initWithFrame:self.view.frame];
        [self.view addSubview:tableView];
    }
    return self;
}

我发现在处理新项目时我总是遇到同样恼人的问题。添加的子视图最终位于导航栏下方20个像素处。

为什么我最终以{{0,20},{320,460}}为self.view.frame?我不想强制使用CGRect框架,我宁愿根据视图控制器的框架设置它,所以我不会遇到动态框架更改的问题(网络,电话等状态栏更高的问题)

更新:还注意到我的帧高达460。这也没有意义。在我的情况下,我实际上有一个标签栏,所以高度不应该减去状态栏,减去uinavigationbar并减去标签栏的高度?

由于

2 个答案:

答案 0 :(得分:7)

只有在调用-viewWillAppear-viewDidAppear方法时,UIView的框架才会获取有效参数。您不应该依赖框架并在之前使用它进行任何计算 此外,在调用view方法之前,不应使用(来自其他对象)UIViewController(UItableViewController)的-viewDidLoad属性,因此不应使用视图并在init方法中向其添加任何控制器,仅在-loadView-viewDidLoad中(更好)。在这些方法中添加子视图并在出现之前设置其框架 在viewController的生命周期视图中可以多次加载和卸载(例如didReceiveMemoryWarning卸载视图),视图永远不会加载。

答案 1 :(得分:2)

您正在混合两种不同的坐标系。 self.view的框架在窗口的坐标系中定义(或者它的父视图是什么)。 tableView的框架在self.view的坐标系中定义。

如果您想要填充整个视图,请设置

subView.frame = parentView.bounds;

bounds在视图自己的坐标系中定义。 frame在其父视图的坐标系中定义。所以subView.frame和parentView.bounds是相同的坐标系。

当您设置subview.frame = parentView.frame时,它们最终不会超过20克= 20盎司。主视图起源于(0,20);子视图的起源为(0,20),但是在不同的坐标系中。在窗口坐标系中(0,40)。