bohan
bohan

Reputation: 1699

To create a new UIWindow over the main window

In my app I want to create a new UIWindow over the main UIWindow, And I wrote as following, but it don't works. first, i create a UIWindow as the main window, and then make it key and visible, and then create a new UIWindow overlay, but nothing happens.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor redColor];
    ViewController *vc = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];
    UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
    window1.backgroundColor = [UIColor redColor];
    window1.windowLevel = UIWindowLevelAlert;
    [window1 makeKeyAndVisible];
    return YES;
}

Upvotes: 46

Views: 86489

Answers (10)

Mr.SwiftOak
Mr.SwiftOak

Reputation: 1844

SWIFT 5

In iOS13 and higher you must create UIWindow with windowScene: initializer as follows let overlayWindow = UIWindow(windowScene: YourScene). For lower iOS versions you should use frame: initializer as follows let overlayWindow = UIWindow(frame: YourFrame).

After creating UIWindow instance you can use code to display window as is written in @Nick Greg answer:

overlayWindow.windowLevel = UIWindow.Level.alert
overlayWindow.rootViewController = UIViewController()//your controller or navController
overlayWindow.makeKeyAndVisible()

Upvotes: 5

Yulong Xiao
Yulong Xiao

Reputation: 201

Your window1 object is a local variable, when the code runs out of this method, this object does not exist any more. Any UIWindow object we created will be add to the [[UIApplication sharedApplication] windows], but this array only keeps a weak reference to any UIWindow object, so it's up to your own code to keep the window object existing. Why apple implemented it like this, I guess, is [UIApplication sharedApplication] object exists as long as the app runs, doing so to avoid keeping the UIWindow objects which only needs to exist for a while living in the memory "forever".

What's more, your code could run with MRC.

Upvotes: 11

Nick Greg
Nick Greg

Reputation: 241

If you are using a window scene try this:

private var overlayWindow: UIWindow!

if let currentWindowScene = UIApplication.shared.connectedScenes.first as?  UIWindowScene {
        overlayWindow = UIWindow(windowScene: currentWindowScene)
    }
overlayWindow.windowLevel = UIWindow.Level.alert
overlayWindow.rootViewController = UIViewController()//your controller or navController
overlayWindow.makeKeyAndVisible()

Upvotes: 15

Tien Nguyen Minh
Tien Nguyen Minh

Reputation: 124

func createAdsWindow(){
    let frame = CGRect.init(0, UIScreen.main.bounds.height - 60, UIScreen.main.bounds.width, 60)
    adsWindow = UIWindow.init(frame: frame)
    adsWindow!.backgroundColor = UIColor(colorBackground)
    let adsViewController = UIViewController.init()
    adsViewController.view.backgroundColor = UIColor.red
    adsWindow?.rootViewController = adsViewController
    adsWindow?.windowLevel = UIWindow.Level(rawValue: 2)
    adsWindow?.makeKeyAndVisible()
}

Upvotes: 0

Mohamed Obaya
Mohamed Obaya

Reputation: 2583

if you just need to change shared window ViewController in swift 5

UIApplication.shared.keyWindow?.rootViewController = UINavigationController(rootViewController: yourViewController)

Upvotes: 1

user6618855
user6618855

Reputation: 31

Swift 4

To avoid memory leak, I prefer to initialise my custom window in this way, as proposed by Apple :

If you want to provide a custom window for your app, you must implement the getter method of this property and use it to create and return your custom window.

Example:

var myCustomWindow: UIWindow? = CustomWindow(frame: UIScreen.main.bounds)

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    let mainController: MainViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as! MainViewController
    self.myCustomWindow?.rootViewController = mainController
    self.myCustomWindow?.makeKeyAndVisible()
}

Upvotes: 3

bohan
bohan

Reputation: 1699

UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
window1.backgroundColor = [UIColor redColor];
window1.windowLevel = UIWindowLevelAlert;
[window1 makeKeyAndVisible];

Finally I know why it doesn't work, because window1 is a method var, and it will lost after the method executed. So I declare a new @property for it, as

@property (strong, nonatomic) UIWindow *window2;

and change the code like

UIWindow *window2 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 80, 320, 320)];
window2.backgroundColor = [UIColor redColor];
window2.windowLevel = UIWindowLevelAlert;
self.window2 = window2;
[window2 makeKeyAndVisible];

it works!

Upvotes: 68

SwiftArchitect
SwiftArchitect

Reputation: 48552

Xcode 8 + Swift

class ViewController: UIViewController {
    var coveringWindow: UIWindow?
    
    func coverEverything() {
        coveringWindow = UIWindow(frame: (view.window?.frame)!)
        
        if let coveringWindow = coveringWindow {
            coveringWindow.windowLevel = UIWindowLevelAlert + 1
            coveringWindow.isHidden = false
        }
    }
}

According to the documentation, to receive events that do not have a relevant coordinate value, such as keyboard entry, make it key instead of merely ! isHidden:

coveringWindow.makeKeyAndVisible()

You can even control the transparency of its background, for a smoke effect:

coveringWindow.backgroundColor = UIColor(white: 0, alpha: 0.5)

Note that such window needs to handle orientation changes.

Upvotes: 13

Ajith K Jose
Ajith K Jose

Reputation: 131

In swift a new UIWindow can be added as follows..

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var viewController: ViewController?
    var navigationController: UINavigationController?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
        self.viewController = ViewController(nibName: "ViewController", bundle:NSBundle.mainBundle())
        self.navigationController = UINavigationController(rootViewController: self.viewController!)
        self.window!.rootViewController = self.navigationController
        //  self.window!.addSubview(self.viewController!.view)
        self.window!.makeKeyAndVisible()
        return true
    }

    //Other methods..
}

Upvotes: -1

Nirav Gadhiya
Nirav Gadhiya

Reputation: 6342

try adding a UIView on mainWindow not another UIWindow like...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor redColor];
    ViewController *vc = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = vc;
    [self.window makeKeyAndVisible];
    UIView * viewAlert = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
    viewAlert.backgroundColor = [UIColor redColor];
    [self.window.rootViewController.view addSubView:viewAlert];
    /* or you can use following..
    [self.window addSubView:viewAlert];
    */
    [viewAlert release]; //FOR NON ARC
    return YES;
}

Upvotes: 0

Related Questions