一劳永逸地解决 initWithFrame:self.view.frame 20 像素(状态栏)问题
我有一个简单的 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 像素处。
为什么我最终得到 self.view.frame 的 {{0, 20}, {320, 460}} ?我不想强制 CGRect 框架,我宁愿根据视图控制器的框架设置它,这样我就不会遇到动态框架更改的问题(状态栏较高的网络共享、电话呼叫等) 。
更新:还注意到我的框架高度为 460。这也没有道理。就我而言,我实际上有一个选项卡栏,所以高度不应该减去状态栏、减去 uinavigationbar 并减去选项卡栏高度吗?
谢谢
I have a simple UINavigationController. In the init method I am creating and adding a UITableView as a subview.
- (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;
}
I find I always run into the same annoying issue when working with new projects. Added subviews end up 20 pixels below the navigation bar.
Why is it that I end up with {{0, 20}, {320, 460}} for self.view.frame? I don't want to force the CGRect frame, I'd rather set it based on the view controller's frame so I don't run into issues with dynamic frame changes (tethering, phone call, etc. where the status bar is taller).
Update: Also noticed I am getting a 460 height for the frame. That doesn't make sense either. In my case, I actually have a tab bar, so the height shouldn't that be minus the status bar, minus the uinavigationbar and minus the tab bar heights?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
UIView 的 Frame 仅在调用
-viewWillAppear
、-viewDidAppear
方法时才采用有效参数。您不应依赖框架并在此之前使用它进行任何计算。另外,在调用
-viewDidLoad
方法之前,您不应该使用(来自其他对象)UIViewController (UItableViewController) 的view
属性,因此您不应该使用视图并向其添加任何控制器在init
方法中,仅在-loadView
或(更好)在-viewDidLoad
中。在这些方法中添加子视图并在出现之前设置其框架。在viewController的生命周期中,视图可以被加载和卸载多次(例如didReceiveMemoryWarning卸载视图),视图根本无法加载。
Frame of UIView takes valid arguments only when
-viewWillAppear
,-viewDidAppear
methods are called. You should NOT rely on frame and make any calculations using it before.Also you should NOT use (from other objects)
view
property of UIViewController (UItableViewController) before-viewDidLoad
method is called, so you should not use view and add any controllers to it ininit
method, only in-loadView
or (better) in-viewDidLoad
. Add your subview in these methods and set its frame before appearance.In viewController's lifecycle view can be loaded and unloaded many times (for example didReceiveMemoryWarning unloads view), view can never load at all.
您正在混合两个不同的坐标系。 self.view 的框架是在窗口的坐标系(或任何它的父视图)中定义的。 tableView 的框架是在 self.view 的坐标系中定义的。
如果您希望某些内容填充整个视图,请
在视图自己的坐标系中定义设置边界。框架是在其父视图的坐标系中定义的。所以subView.frame和parentView.bounds是同一个坐标系。
当您设置
subview.frame =parentView.frame
时,它们最终不会成为超过 20 克 = 20 盎司的同一物体。主视图的原点为 (0, 20);子视图的原点位于 (0, 20),但位于不同的坐标系中。在窗口坐标系中为 (0, 40)。You are mixing two different coordinate systems. self.view's frame is defined in the window's coordinate system (or whatever it's parent view is). tableView's frame is defined in self.view's coordinate system.
If you want something to fill the entire view, set
bounds is defined in a view's own coordinate system. frame is defined in its parent view's coordinate system. So subView.frame and parentView.bounds are the same coordinate system.
When you set
subview.frame = parentView.frame
, they don't end up being the same thing any more than 20 grams = 20 ounces. The main view has origin at (0, 20); the subview has origin at (0, 20), but in a different coordinate system. In the window coordinate system that's (0, 40).