Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initialize NoticePresenter in didFinishLaunchingWithOptions #11900

Closed
3 tasks
shiki opened this issue Jun 12, 2019 · 0 comments · May be fixed by #23049
Closed
3 tasks

Initialize NoticePresenter in didFinishLaunchingWithOptions #11900

shiki opened this issue Jun 12, 2019 · 0 comments · May be fixed by #23049

Comments

@shiki
Copy link
Member

shiki commented Jun 12, 2019

In #11345, we fixed a UIWindow rotation issue by keeping the UIWindow visible and hiding it on the next run loop (DispatchQueue.main.async). After talking to Apple engineers at WWDC, it looks like we can avoid doing the hack by moving the NoticePresenter initialization to didFinishLaunchingWithOptions instead of willFinishLaunchingOptions.

Here is a sample code showing that this works. You will have to create an empty application with a single view and replace the AppDelegate contents.

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    private var secondWindowPresenter: SecondWindowPresenter?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Move this to willFinishLaunchingWithOptions to reproduce the rotation bug
        secondWindowPresenter = SecondWindowPresenter()
        return true
    }

    func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.backgroundColor = UIColor.white
        window?.rootViewController = ViewController()

        window?.makeKeyAndVisible()

        // If this is in -didFinishLaunchingWithOptions, the rotation works fine
//        secondWindowPresenter = SecondWindowPresenter()

        return true
    }
}

private class SecondWindowPresenter {
    private let window: UIWindow

    init() {
        let windowFrame: CGRect
        if let mainWindow = UIApplication.shared.keyWindow {
            windowFrame = mainWindow.offsetToAvoidStatusBar()
        } else {
            windowFrame = .zero
        }
        window = UntouchableWindow(frame: windowFrame)
        window.windowLevel = .alert
        window.backgroundColor = UIColor.blue.withAlphaComponent(0.4)

        // Emulate showing the Notice (inside a UIWindow)
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) { [weak self] in
            self?.window.isHidden = false
        }
    }
}

private extension UIWindow {
    func offsetToAvoidStatusBar() -> CGRect {
        return self.frame.insetBy(dx: Offsets.minimalEdgeOffset, dy: Offsets.minimalEdgeOffset)
    }

    private enum Offsets {
        static let minimalEdgeOffset: CGFloat = 1.0
    }
}

@objc class UntouchableWindow: UIWindow {
    override init(frame: CGRect) {
        super.init(frame: frame)
        rootViewController = UIViewController()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Proposed Tasks

@nheagy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants