在 iOS 单视图应用程序中,self.view.bounds 最早设置正确的时间是啥时候?
Posted
技术标签:
【中文标题】在 iOS 单视图应用程序中,self.view.bounds 最早设置正确的时间是啥时候?【英文标题】:On an iOS single view app, when is the earliest time that self.view.bounds is set correctly?在 iOS 单视图应用程序中,self.view.bounds 最早设置正确的时间是什么时候? 【发布时间】:2012-08-25 03:26:04 【问题描述】:我正在尝试添加一个覆盖整个屏幕的 UITableView
对象,通过
UITableView *tabelView = [[UITableView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:tabelView];
但我意识到即使将物理 iPad 2 旋转到横向模式,self.view.bounds
在viewDidLoad
和viewWillAppear
中也是0, 0, 768, 1004
。只有viewDidAppear
终于0, 0, 1024, 748
self.view.bounds
正确设置为0, 0, 1024, 748
的最早时间是什么时候?如果viewDidAppear
是那个,那么我必须在那里创建UITableView
,如果“启动图像”是静态横向空白表,那么当调用viewDidAppear
时屏幕会闪烁白屏,然后表格被添加并被看到,所以看到一闪而过的白屏。
那么最早将self.view.bounds
正确设置为0, 0, 1024, 748
的时间是什么时候?似乎需要稍早于viewDidAppear
,以便绘制空白表格(带有灰色线条),并显示它并无缝显示以覆盖Launch图像。如果表格是在viewDidLoad
或viewWillAppear
中使用self.view.bounds
创建的,则表格最终为768 磅宽,适用于纵向模式。
更新:我只是尝试添加 Launch 图像,但由于某种原因,即使在 viewDidAppear
中添加了 UITableView
,“白屏闪烁”也没有发生……我没有不知道为什么,但是之前如果我使用CALayer
和位图来显示内容,并且没有使用任何视图或drawRect
,那么就会出现flash...顺便说一句,我发现的最早的是@987654345 @,然后是viewDidLayoutSubviews
,两者都发生在viewDidAppear
之前,并且都将self.view.bounds
显示为0, 0, 1024, 748
更新 2:如果视图制作复杂且耗时怎么办?为了进行测试,我在tableView:cellForRowAtIndexPath
中添加了一个usleep(100000);
,以使每个单元格休眠0.1 秒,并且确实发生了“闪光”……但是单元格和表格应该重量轻且制作速度快,但是如果有怎么办制作其他类型的视图是否更耗时?如果我将UITableView
创建移动到viewWillLayoutSubviews
,那么显示东西还是很慢,但至少没有“闪光”。但是,稍后当我旋转设备时,它实际上再次调用viewWillLayoutSubviews
并将另一个表添加到主视图(具有正确的屏幕尺寸),因此viewWillLayoutSubviews
将需要首先删除任何旧表视图(如果有),或者只需调整旧的大小,不要添加新的。
【问题讨论】:
虽然 self.view.bounds 稍后会更新,但如果您使用 [UIApplication sharedApplication].statusBarOrientation 获取界面方向,您可以在等待设置边界之前决定如何调整表格大小。 @Luke 如果这行得通,这可能有点小题大做,因为如果未来的 ios 设备问世,它不是 iPhone 或 iPad 分辨率,我们需要依靠@ 987654356@? Apple 往往对这些事情很友好,但是虽然我理解你在说什么,但无论如何你都可以这样做(因为你想在视图出现之前绘制表格)然后比较您使用最终 self.view.bounds 生成的框架,然后根据需要进行调整。 @Luke 请查看问题中的更新 UIViewController returns invalid frame? 的可能重复项 【参考方案1】:避免flash最简单的方法是在viewDidLoad
中创建table view,并正确设置table view的autoresizing mask,让系统自动让table view填满它的superview:
- (void)viewDidLoad
[super viewDidLoad];
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:tableView];
否则,您可以看到最终视图边界的最早时间是在视图控制器的viewWillLayoutSubviews
方法中。您将在viewDidLoad
中添加一次表格视图,然后在viewWillLayoutSubviews
或之后调用的方法中调整其框架。有关详细信息,请参阅我对 UIViewController returns invalid frame? 的回复。
【讨论】:
实际上,它确实有效 - 即使我在单元格数据源提供程序中添加sleep(1)
也没有闪存,所以即使表格出来很慢(比如,5 或10 秒),没有闪烁,这是一个有趣的概念:我们首先将视图设置为“不正确”的大小,然后让“调整大小”处理它,然后再将其显示在屏幕上
还有viewWillResizeSubviews
吗?我用谷歌搜索并搜索了您答案中的链接,但没有看到这样的调整大小消息?
没有viewWillResizeSubviews
消息。视图仅在执行自动布局时调整其子视图的大小,然后您会立即收到viewWillLayoutSubviews
。
因为您在回答中提到了viewWillResizeSubviews
...它属于哪里?【参考方案2】:
我试图解决一个类似的问题 - 我想根据在 Interface Builder 中添加的 UIView
的大小以编程方式加载一些 UI 元素。
在viewDidLoad
和viewWillAppear
内部,UIView
仍未设置其框架/边界。将我的代码放在 viewDidAppear
中是可行的,但这意味着 UI 会随着更新而“闪烁”,而不是在将 UIViewController
推送到导航堆栈时显示为已经加载。
我发现覆盖 viewDidLayoutSubviews
解决了这个问题 - 那时,视图有它的边界和框架集 - 我可以在 viewDidAppear
之前添加相对于它的大小的我自己的子视图。
最终结果是 UI 在出现之前就已正确加载,因此不会为用户“闪现”。
【讨论】:
以上是关于在 iOS 单视图应用程序中,self.view.bounds 最早设置正确的时间是啥时候?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ios7 中将 UIView 对象添加到 self.view.window?
添加滚动视图时,所有视图都显示在导航栏后面的self.view顶部