UIAlertController is moved to buggy position at top of screen when it calls `presentViewController:`

前端 未结 12 1305
心在旅途
心在旅途 2020-12-08 06:36

Presenting a view from a UIAlertController moves the alert to a buggy position at the top-left corner of the screen. iOS 8.1, device and simulator.

We h

相关标签:
12条回答
  • 2020-12-08 07:03

    EDIT: Tested in 2020, Xcode 11.2, iOS 13

    If anyone still looking for a better answer to this, then here is my solution. Use updateConstraints method to readjust the constraints.

    your_alert_controller_obj.updateConstraints()
    
    0 讨论(0)
  • 2020-12-08 07:03
    var kbHeight: CGFloat = 0    
    
    override func keyboardWillShow(_ notification: Notification) {
        if let userInfo = notification.userInfo {
            if let keyboardSize =  (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
                kbHeight = keyboardSize.height
                self.animateTextField(up: true)
            }
        }
    }
    
    override func keyboardWillHide(_ notification: Notification) {
          self.animateTextField(up: false)
    }
    
    
    func animateTextField(up: Bool) {
        let movement = (up ? -kbHeight : kbHeight)
        UIView.animate(withDuration: 0.3, animations: {
            self.view.frame =  CGRect.offsetBy(self.view.frame)(dx: 0, dy: movement)
        })
    }
    
    0 讨论(0)
  • 2020-12-08 07:05

    I encountered a situation where sometimes a modal view would present itself on top of a an alert (silly situation, I know), and the UIAlertController could appear in the top left (like the 2nd screenshot of the original question), and I found a one-liner solution that seems to work. For the controller that's about to be presented on the UIAlertController, change its modal presentation style like so:

    viewControllerToBePresented.modalPresentationStyle = .OverFullScreen
    

    This should be done just before you call presentViewController(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion completion: (() -> Void)?)

    0 讨论(0)
  • 2020-12-08 07:07

    A quick fix is to always present the View Controller on top of a new UIWindow:

    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    window.rootViewController = [[UIViewController alloc] init];
    window.windowLevel = UIWindowLevelNormal;
    [window makeKeyAndVisible];
    [window.rootViewController presentViewController: viewController
                                            animated:YES 
                                          completion:nil];
    
    0 讨论(0)
  • 2020-12-08 07:09

    I think that you only should to categorize UIAlertController like this:

    @implementation UIAlertController(UIAlertControllerExtended)
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    
        if (self.preferredStyle == UIAlertControllerStyleAlert) {
            __weak UIAlertController *pSelf = self;
    
            dispatch_async(dispatch_get_main_queue(), ^{
                CGRect screenRect = [[UIScreen mainScreen] bounds];
                CGFloat screenWidth = screenRect.size.width;
                CGFloat screenHeight = screenRect.size.height;
    
                [pSelf.view setCenter:CGPointMake(screenWidth / 2.0, screenHeight / 2.0)];
                [pSelf.view setNeedsDisplay];
            });
        }
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-08 07:15

    I was having this issue as well. If I presented a view controller while a UIAlertController was presented, the alert would go to the top left.

    My fix is to refresh the center of the UIAlertController's view in viewDidLayoutSubviews; achieved by subclassing UIAlertController.

    class MyBetterAlertController : UIAlertController {
    
        override func viewDidLayoutSubviews() {
            super.viewDidLayoutSubviews()
    
            let screenBounds = UIScreen.mainScreen().bounds
    
            if (preferredStyle == .ActionSheet) {
                self.view.center = CGPointMake(screenBounds.size.width*0.5, screenBounds.size.height - (self.view.frame.size.height*0.5) - 8)
            } else {
                self.view.center = CGPointMake(screenBounds.size.width*0.5, screenBounds.size.height*0.5)
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题