解决 UIAlterController 不居中问题
最后更新:2017-06-30
现象描述
新公司做的解决的第一个bug 就是 UIAlterController 不居中,莫名其妙的飞出屏幕之外
找了很久的答案,最终在苹果论坛看到了相关的描述
We have noticed this in an app when we attempt to present a view from the current "top-most" view. If a UIAlertController happens to be the top-most view we get this behavior. We have changed our code to simply ignore UIAlertControllers, but I'm posting this in case others hit the same issue (as I couldn't find anything).
我们注意到,当我们试图从“top-most”的view present 一个view 时候,当 UIAlertController 刚还是 ““top-most”” 的视图,就会出现这个情况
解决方案:
OC:
在 UIAlertControllers分类里面写
/*
* UIAlertControllers (of alert type, and action sheet type on iPhones/iPods) get placed in crazy
* locations when you present a view controller over them. This attempts to restore their original placement.
*/
- (void)_my_fixupLayout
{
if (self.preferredStyle == UIAlertControllerStyleAlert && self.view.window)
{
CGRect myRect = self.view.bounds;
CGRect windowRect = [self.view convertRect:myRect toView:nil];
if (!CGRectContainsRect(self.view.window.bounds, windowRect) || CGPointEqualToPoint(windowRect.origin, CGPointZero))
{
CGPoint center = self.view.window.center;
CGPoint myCenter = [self.view.superview convertPoint:center fromView:nil];
self.view.center = myCenter;
}
}
else if (self.preferredStyle == UIAlertControllerStyleActionSheet && self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPhone && self.view.window)
{
CGRect myRect = self.view.bounds;
CGRect windowRect = [self.view convertRect:myRect toView:nil];
if (!CGRectContainsRect(self.view.window.bounds, windowRect) || CGPointEqualToPoint(windowRect.origin, CGPointZero))
{
UIScreen *screen = self.view.window.screen;
CGFloat borderPadding = ((screen.nativeBounds.size.width / screen.nativeScale) - myRect.size.width) / 2.0f;
CGRect myFrame = self.view.frame;
CGRect superBounds = self.view.superview.bounds;
myFrame.origin.x = CGRectGetMidX(superBounds) - myFrame.size.width / 2;
myFrame.origin.y = superBounds.size.height - myFrame.size.height - borderPadding;
self.view.frame = myFrame;
}
}
}
- (void)viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
[self _my_fixupLayout];
}
SWIFT
extension UIAlertController {
open override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
fixupLayout()
}
private func fixupLayout() {
if preferredStyle == .alert && view.window != nil {
let myRect = view.bounds
let windowRect = view.convert(myRect, to: nil)
guard let window = view.window else {
return
}
guard let superview = view.superview else {
return
}
if !window.bounds.contains(windowRect) || windowRect.origin.equalTo(CGPoint.zero) {
let myCenter = superview.convert(window.center, from: nil)
view.center = myCenter
}
} else if preferredStyle == .actionSheet && self.traitCollection.userInterfaceIdiom == .phone && view.window != nil {
let myRect = view.bounds
let windowRect = view.convert(myRect, to: nil)
guard let window = view.window else {
return
}
guard let superview = view.superview else {
return
}
if !(window.bounds.contains(windowRect)) || windowRect.origin.equalTo(CGPoint.zero) {
let screen = window.screen
let borderPadding = ((screen.nativeBounds.width / screen.nativeScale) - myRect.size.width) / 2.0
var myFrame = view.frame
let superBounds = superview.bounds
myFrame.origin.x = superBounds.maxX - myFrame.width / 2
myFrame.origin.y = superBounds.height - myFrame.height - borderPadding
self.view.frame = myFrame
}
}
}
}