在当前显示的视图控制器上呈现 UIWebview

Posted

技术标签:

【中文标题】在当前显示的视图控制器上呈现 UIWebview【英文标题】:Present UIWebview on top on currently displayed view controller 【发布时间】:2013-07-25 15:58:34 【问题描述】:

我正在尝试在当前显示的视图控制器之上以模态方式显示 UIWebview。弹出 webview 的代码位于静态库中,不知道它所在的应用程序的视图控制器层次结构。下面的代码适用于我的测试用例,但不确定它是否适用于所有可能的视图控制器层次结构.

UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController];
UIViewController *presentedVC = [rootViewController presentedViewController];
if (presentedVC) 
    // We have a modally displayed viewcontroller on top of rootViewController.
    if (!presentedVC.isBeingPresented) 
    [presentedVC presentViewController:vc animated:YES completion:^
        //
    ];
 else 
    rootViewController presentViewController:vc animated:YES completion:^
        //
    ];

presentViewController 总是给当前可见的视图控制器吗?

【问题讨论】:

嗯,如果这行得通,我会感到惊讶。除非我要疯了,否则 keyWindow 会返回上次调用到makeKeyAndVisisble 的当前可见窗口。要获得当前呈现的视图控制器,这一切都取决于您的层次结构。如果你有一个模态屏幕,那就是它,如果没有,并且你有导航控制器作为根,你将不得不查看堆栈的顶部。鉴于有这么多设置导航层的方法,我认为很难找到顶视图控制器。.. 我认为您需要将当前视图控制器作为属性传递给您的库。 @MarcusAdams 这绝对是一个选择,但我试图让使用静态库的开发人员对此透明。 @feliun 我添加了对presentedVC 是否为零的检查。如果在 rootViewController 之上没有模态显示的视图控制器,似乎 presentVC 总是为零。 【参考方案1】:

如果您想要在应用程序中显示的任何视图控制器顶部模态显示UIWebView,则不需要“最顶层”。获取根视图控制器就足够了。每当我想在其他所有内容之上呈现视图时,我都会一直这样做。 您只需要引用库中的根视图控制器:

self.rootVC = [[[[UIApplication sharedApplication] delegate] window] rootViewController];

有了这个参考,你现在有两个选择:

第一个是使用UIViewController 的方法presentViewController:animated:completion: 显示另一个视图控制器,其中将包含您的UIWebView

第二个选项是通过添加一个覆盖整个屏幕的子视图来伪造模态视图控制器,具有(半)透明背景,并包含您想要“模态”显示的视图。这是一个例子:

@interface FakeModalView : UIView // the *.h file

@property (nonatomic, retain) UIWebView *webView;
@property (nonatomic, retain) UIView *background; // this will cover the entire screen

-(void)show; // this will show the fake modal view
-(void)close; // this will close the fake modal view

@end

@interface FakeModalView () // the *.m file

@property (nonatomic, retain) UIViewController *rootVC; 

@end

@implementation FakeViewController
@synthesize webView = _webView;
@synthesize background = _background;
@synthesize rootVC = _rootVC;

-(id)init 
    self = [super init];
    if (self) 

        [self setBackgroundColor: [UIColor clearColor]]; 
        _rootVC = self.rootVC = [[[[[UIApplication sharedApplication] delegate] window] rootViewController] retain];
        self.frame = _rootVC.view.bounds; // to make this view the same size as the application

        _background = [[UIView alloc] initWithFrame:self.bounds];
        [_background setBackgroundColor:[UIColor blackColor]];
        [_background setOpaque:NO];
        [_background setAlpha:0.7]; // make the background semi-transparent

        _webView = [[UIWebView alloc] initWithFrame:CGRectMake(THE_POSITION_YOU_WANT_IT_IN)];

        [self addSubview:_background]; // add the background
        [self addSubview:_webView]; // add the web view on top of it
    
    return self;


-(void)dealloc  // remember to release everything

    [_webView release];
    [_background release];
    [_rootVC release];

    [super dealloc];


-(void)show 

    [self.rootVC.view addSubview:self]; // show the fake modal view


-(void)close 

    [self removeFromSuperview]; // hide the fake modal view


@end

如果您有任何其他问题,请告诉我。

希望这会有所帮助!

【讨论】:

第一个选项(使用 rootViewController)不会起作用,因为您可能有一个已经在 rootViewController 顶部模态显示的视图控制器。我从这种方法开始,并在上面描述的场景中收到此警告: 上的 其视图不在窗口层次结构中!” 我会尝试第二个选项并告诉你。

以上是关于在当前显示的视图控制器上呈现 UIWebview的主要内容,如果未能解决你的问题,请参考以下文章

在 UIWebView 之上呈现情节提要的 ViewController

在当前视图控制器下显示新的视图控制器

UIWebView 中的嵌入式 youtube 播放器正在破坏视图层次结构

呈现小Modal VIewController Objective C

模式视图中的 UIWebview 在横向模式下以纵向显示

presentViewController 不显示呈现视图控制器上的所有元素