从 UIAlertController
呈现视图会将警报移动到屏幕左上角的错误位置 . iOS 8.1,设备和模拟器 .
当我们尝试从当前“最顶层”视图中呈现视图时,我们在应用程序中注意到了这一点 . 如果UIAlertController恰好是最顶层的视图,我们会得到这种行为 . 我们已经更改了我们的代码以简单地忽略UIAlertControllers,但我发布这个以防其他人遇到同样的问题(因为我找不到任何东西) .
我们已将此分离为一个简单的测试项目,该问题底部的完整代码 .
-
在新的Single View Xcode项目中的View Controller上实现
viewDidAppear:
. -
提出
UIAlertController
警报 . -
警报控制器立即调用
presentViewController:animated:completion:
显示然后关闭另一个视图控制器:
presentViewController:...
动画开始的那一刻,UIAlertController被移动到屏幕的左上角:
当 dismissViewControllerAnimated:
动画结束时,警报已进一步移动到屏幕的左上边缘:
完整代码:
- (void)viewDidAppear:(BOOL)animated {
// Display a UIAlertController alert
NSString *message = @"This UIAlertController will be moved to the top of the screen if it calls `presentViewController:`";
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"UIAlertController iOS 8.1" message:message preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"I think that's a Bug" style:UIAlertActionStyleCancel handler:nil]];
[self presentViewController:alert animated:YES completion:nil];
// The UIAlertController should Present and then Dismiss a view
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.backgroundColor = self.view.tintColor;
[alert presentViewController:viewController animated:YES completion:^{
dispatch_after(0, dispatch_get_main_queue(), ^{
[viewController dismissViewControllerAnimated:YES completion:nil];
});
}];
// RESULT:
// UIAlertController has been moved to the top of the screen.
// http://i.imgur.com/KtZobuK.png
}
上面的代码中是否有任何导致此问题的内容?是否存在任何可以从UIAlertController无错误地呈现视图的替代方案?
rdar:// 19037589
http://openradar.appspot.com/19037589
8 回答
rdar://19037589被Apple关闭
我遇到过一种情况,有时模态视图会出现在警报之上(愚蠢的情况,我知道),而UIAlertController可能出现在左上方(如2nd screenshot of the original question),我找到了一个单行解决方案,似乎工作 . 对于即将在UIAlertController上呈现的控制器,更改其模式表示样式,如下所示:
这应该在您致电
presentViewController(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion completion: (() -> Void)?)
之前完成这有点令人失望......将警报移动到UIViewControllers,但随后禁止对它们进行常规使用 . 我在一个类似的应用程序上工作 - 它有时需要跳转到一个新的用户上下文,并且这样做会在那里提供一个新的视图控制器 . 实际上,警报是视图控制器在这种情况下几乎更好,因为它们将被保留 . 但是现在我们已经切换到UIViewControllers,我们看到相同的位移 .
我们可能必须提出一个不同的解决方案(可能使用不同的窗口),如果顶级是UIAlertController,我们可能会避免显示 . 但是,可以恢复正确的定位 . 这可能不是一个好主意,因为如果Apple改变了他们的屏幕定位,代码可能会破坏,但是如果非常需要这个功能,则下面的子类似乎可以工作(在iOS8中) .
Apple可能会认为视图定位是私有的,因此以这种方式恢复它可能不是最好的主意,但它现在可以使用 . 也许可以在-presentViewController:animated:的覆盖中存储旧框架,并简单地恢复它而不是重新计算 .
可以调整UIAlertController本身来完成与上面相同的操作,这也包括你无法控制的代码所呈现的UIAlertControllers,但我更喜欢只在那些苹果要修复的bug的地方使用swizzles(因此有是一个可以删除混合的时代,我们允许现有的代码“正常工作”,而不是为了解决错误而解决问题) . 但是,如果这是苹果公司不会解决的问题(如他们的回复所示,如此处的另一个答案所述),那么通常有一个单独的类来修改行为更安全,因此您只在已知情况下使用它 .
我认为你应该像这样对UIAlertController进行分类:
我也有这个问题 . 如果我在呈现UIAlertController时呈现了一个视图控制器,则警报将转到左上角 .
我的修复是刷新UIAlertController视图的中心viewDidLayoutSubviews;通过子类化UIAlertController实现 .
除了Carl Lindberg's answer还有两种情况也应该考虑在内:
设备旋转
警报内有文本字段时的键盘高度
那么,对我有用的完整答案:
此外,如果使用类别,则需要以某种方式存储键盘高度,如下所示:
用户
manoj.agg
将此答案发布到了Open Radar bug report,但是说:在这里发布他的答案为后代 . 我没有测试/评估它 .
Step 1:
创建一个继承自
UIViewController
的自定义View Controller并实现UIPopoverPresentationControllerDelegate
:Step 2:
全屏显示视图,使用演示文稿popover:
我遇到了类似的问题,其中密码输入视图需要显示在任何其他视图控制器的顶部,包括UIAlertControllers . 上面的代码帮助我解决了这个问题 . iOS 8中值得注意的变化是
UIAlertController
继承自UIViewController
,而UIAlertView
则不然 .