使用公共/非公共/私有API在设备上获得顶级UIWIndow / UIView

时间:2014-09-25 07:10:08

标签: ios objective-c

我正在尝试找出如何使用非公开/私有api查找最顶层的视图,有没有办法(iOS 7.1.2)?

修改

也许我不清楚, 无论现在哪个应用程序处于活动状态(Facebook,WhatsApp,游戏,锁屏,日历等),我都希望得到最顶层的视图。

4 个答案:

答案 0 :(得分:6)

选项

如果我理解正确,您希望在另一个应用程序窗口的顶部显示UIView。在应用程序沙箱中,您只能访问自己的应用程序窗口。然而,越狱将允许你这样做,但这并不简单。

为了在应用程序之上显示视图,您有三种选择。您选择哪个选项取决于您要做的事情。

  1. 将代码注入第三方应用程序
  2. 将代码注入SpringBoard
  3. 使用方法1和2的组合。
  4. 选项1

    如果您选择使用此路由,则代码将在每个第三方应用程序中运行。这允许您修改应用程序的视图层次结构以显示您自己的窗口,甚至可以修改现有窗口。由于您的代码在应用程序中运行,您只需调用:

    即可获得密钥窗口
    [[UIApplication sharedApplication] keyWindow]
    

    选项2

    如果选择此选项,则无论打开哪个应用程序,您的代码都将运行。通过获取主窗口,您可以显示任何内容的UI,包括系统警报。我在rpendleton/tutorials/so-26032688向GitHub发布了一个这样的例子。该示例在用户将手机从静音状态中随时显示警报。检索SpringBoard窗口的代码是:

    [[NSClassFromString(@"SBUIController") sharedInstance] window]
    

    选项3

    第三个选项,也是您可能最终使用的选项,是选项1和2的组合。在这种情况下,您将代码注入第三方应用程序,然后与SpringBoard通信决定需要做什么。通常,您的应用程序将与SpringBoard通信,然后SpringBoard可以将该信息转发到所需的应用程序。您可以直接在您的应用程序和第三方应用程序之间进行通信,但我没有尝试过。

    通信

    为了在您的应用程序与SpringBoard /其他第三方应用程序之间进行通信,您需要使用消息传递系统。一种简单的方法是通过一个名为RocketBootstrap的开源库。

    截图

    左侧的屏幕截图来自我在GitHub上发布的示例,右侧的屏幕截图来自我的一个调整AppScan。虽然我在两者中都有提醒,但你可以显示你想要的任何视图。

    Example 2 screenshots

答案 1 :(得分:0)

尝试像这样获取AppDelegate的窗口

UIWindow *window = ((AppDelegate*)[UIApplication sharedApplication].delegate).window;

然后访问窗口的最后一个对象

[[window subviews] objectAtIndex:0];

或者像这样

[[window subviews]lastObject];

如果你想添加子视图

[[[window subviews] objectAtIndex:0] addSubview:view];

答案 2 :(得分:0)

阅读问题和评论这是你正在寻找的...我想,不是我看到的最详细的问题:

UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = self;
window.windowLevel = [[UIApplication sharedApplication] keyWindow].windowLevel + 1;
[window makeKeyAndVisible];

您希望将其用作顶部所需的视图控制器的一部分。

答案 3 :(得分:0)

你的问题不完全清楚,你能解释一下你为什么需要这样做吗? 顺便说一句,你最需要的是关键窗口,如文档中所述:

  

键窗口是指定接收键盘的窗口   其他非触摸相关事件。一次只能有一个窗口   关键窗口。

您可以做的是询问应用程序当前关键窗口:

NSArray * array = [[UIApplication sharedApplication] windows];

迭代该数组以找到关键窗口,然后检查其子视图:

UIView * topView = [[window subviews]lastObject]

如果您正在寻找一种模拟警报视图的方法,您应该创建自己的UIWindow,然后添加您的视图控制器来处理"警告"作为rootViewController并使其成为"键和可见"。
这样的事情:

UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
alertWindow.rootViewController = [[AlertViewController alloc] initWithXibNamed:@"AlertXib"];
alertWindow.windowLevel = UIWindowLevelAlert;
[alertWindow makeKeyAndVisible];

当您想要解除时,只需将rootViewController设置为nil并使窗口隐藏 使用根视图控制器方法有助于避免混乱旋转校正。即使在iOS8中旋转。
我找到了一个很好的参考here