【问题标题】:To create a new UIWindow over the main window在主窗口上创建一个新的 UIWindow
【发布时间】:2013-11-15 07:15:54
【问题描述】:

在我的应用程序中,我想在主 UIWindow 上创建一个新的UIWindow,我写了如下内容,但它不起作用。 首先,我创建了一个UIWindow 作为主窗口,然后将其设为关键且可见,然后创建一个新的UIWindow 叠加层,但没有任何反应。

- (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;
}

【问题讨论】:

  • 为什么它对我有用,我的 Xcode 是 V5.0
  • 我在 xCode 4.6 和 5 中尝试过,它可以工作。
  • 和你的模拟器版本?

标签: ios uiwindow


【解决方案1】:
UIWindow *window1 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];
window1.backgroundColor = [UIColor redColor];
window1.windowLevel = UIWindowLevelAlert;
[window1 makeKeyAndVisible];

终于知道为什么不起作用了,因为window1是一个方法var,在方法执行后会丢失。所以我为它声明了一个新的@property,就像

@property (strong, nonatomic) UIWindow *window2;

和 像这样改代码

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

有效!

【讨论】:

  • 为什么不:self.window2 = [[UIWindow alloc] initWithFrame:CGRectMake(0, 80, 320, 320)]; self.window2.backgroundColor = [UIColor redColor]; self.window2.windowLevel = UIWindowLevelAlert; [self.window2 makeKeyAndVisible];
  • 这里几乎是一样的,但是通常——而且大多数情况下,尤其是在并发线程的情况下——最好用它的所有属性完全填充对象实例,然后分配给一个拥有的属性。万一其他线程开始更改 self.window2 属性,而主线程位于块的中间,您将不知道分配的对象的最终属性 - 可能是许多不同替代状态的混合。跨度>
  • 我如何关闭那个窗口?
【解决方案2】:

Xcode 8 + 斯威夫特

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
        }
    }
}

根据the documentation,接收没有相关坐标值的事件,如键盘输入,改为key,而不是仅仅!isHidden

coveringWindow.makeKeyAndVisible()

您甚至可以控制其背景的透明度,以获得烟雾效果:

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

请注意,此类窗口需要处理方向变化。

【讨论】:

  • 谢谢。一件事...... “请注意,这样的窗口需要处理方向变化。”现代iOS现在似乎会自动执行此操作。你怎么看?可能从 iOS9 开始?
  • 我试过了,在 iOS 13 上好像不行,就是窗口不会出现在屏幕上。如果我将 ViewController 设置为其根,我会收到错误消息“不再支持手动将 rootViewController 的视图添加到视图层次结构。请允许 UIWindow 将 rootViewController 的视图添加到视图层次结构本身。”
【解决方案3】:

你的window1对象是一个局部变量,当代码用完这个方法时,这个对象就不存在了。我们创建的任何UIWindow 对象都将被添加到[[UIApplication sharedApplication] windows],但是这个数组只保留对任何UIWindow 对象的弱引用,因此保持窗口对象存在取决于您自己的代码。我猜为什么苹果会这样实现它,是[UIApplication sharedApplication] 对象只要应用程序运行就存在,这样做是为了避免将只需要存在一段时间的UIWindow 对象“永远”存在于内存中。

此外,您的代码可以使用 MRC 运行。

【讨论】:

    【解决方案4】:

    如果你使用的是窗口场景,试试这个:

    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()
    

    【讨论】:

    • UIWindow(windowScene:) 初始化程序是完成这项工作的关键,谢谢!
    【解决方案5】:

    SWIFT 5

    在 iOS13 及更高版本中,您必须使用 windowScene: 初始化器创建 UIWindow,如下所示 let overlayWindow = UIWindow(windowScene: YourScene)。对于较低的 iOS 版本,您应该使用 frame: 初始化器,如下所示 let overlayWindow = UIWindow(frame: YourFrame)

    创建UIWindow 实例后,您可以使用@Nick Greg 回答中所写的代码来显示窗口:

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

    【讨论】:

      【解决方案6】:

      斯威夫特 4

      为避免内存泄漏,我更喜欢按照 Apple 的建议以这种方式初始化我的自定义窗口:

      如果你想为你的应用提供一个自定义窗口,你必须实现这个属性的getter方法,并使用它来创建和返回你的自定义窗口。

      例子:

      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()
      }
      

      【讨论】:

        【解决方案7】:

        如果你只需要在 swift 5 中更改共享窗口 ViewController

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

        【讨论】:

          【解决方案8】:

          尝试在 mainWindow 上添加 UIView 而不是另一个 UIWindow 之类的...

          - (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;
          }
          

          【讨论】:

          • 抱歉 bohan,我不知道,因为我只使用视图。它是否有效?
          【解决方案9】:
          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()
          }
          

          【讨论】:

            【解决方案10】:

            在swift中可以添加一个新的UIWindow,如下所示..

            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..
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-02-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-10-09
              相关资源
              最近更新 更多