如何检测UIWebView的视图布局的完成情况

时间:2012-08-20 18:45:48

标签: ios pdf uiwebview

我想允许用户将缩放因子与文档相关联,并在UIWebView中显示该文档时将其用作起点。但是,似乎webViewDidFinishLoad:仅表示内存中加载的结束,不包括渲染或布局。以下是演示此问题的示例代码:

- (void)viewDidLoad {
    [super viewDidLoad];
    UIWebView *webView = (UIWebView *)self.view;
    webView.delegate = self;
    webView.scalesPageToFit = YES;
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    NSString *urlString = [[NSBundle mainBundle] pathForResource:@"Doc" ofType:@"pdf"];
    NSURL *file = [NSURL fileURLWithPath:urlString];
    [(UIWebView *)self.view loadRequest:[NSURLRequest requestWithURL:file]];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (!webView.isLoading) {
        [webView.scrollView setZoomScale:1.5 animated:YES];
    }
}

对setZoomScale的调用:执行时没有任何效果(即文件以缩放因子1.0显示),显然是因为它发生在滚动视图处于可以处理它的某个状态之前。如果我将上面的最终方法改为以下内容,那么一切都按照我的希望进行。

- (void)delayedZoomMethod {
    [((UIWebView *)self.view).scrollView setZoomScale:1.5 animated:YES];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [self performSelector:@selector(delayedZoomMethod) withObject:nil afterDelay:1.0];
}

这当然是一个坏主意,因为1.0延迟是任意的,对于绝大多数情况来说可能太长,并且在某些未知条件下可能会太短。

文档说,“如果想要自定义Web视图的滚动行为,您的应用程序可以访问滚动视图。”是否有人知道Web视图中的通知或属性或它的滚动视图,我可以观察到该语句变为真时?

3 个答案:

答案 0 :(得分:2)

如果您控制了html代码,这可能有所帮助。我已经能够通过以下方式让html事件触发objC方法。

html事件触发将字符串写入window.location的javascript 然后uiwebview使用uiwebviewdelegate接收具​​有此功能的字符串 web视图:shouldStartLoadWithRequest:navigationType:

这是一种hacky。

但我不认为有办法知道网页视图已经完成渲染,除非您编写了html页面并且可以在页面末尾执行js函数。

答案 1 :(得分:0)

如果您使用UIWebView预览PDF文件,那么它可能不是最佳方式。有一个QLPreViewController(来自iOS 4.0),用于此目的。快速查看预览控制器可以显示以下项目的预览:

  • iWork文件
  • Microsoft Office文档(Office '97及更新版本)
  • 富文本格式(RTF)文档
  • PDF文件
  • 图片
  • 统一类型标识符(UTI)符合的文本文件 public.text类型(请参阅统一类型标识符参考)
  • 逗号分隔值(csv)文件

答案 2 :(得分:-1)

  

如果我将上面的最终方法改为以下内容,一切正常   正如我所希望的那样。

     

这当然是一个坏主意,因为1.0延迟是任意的,   对于绝大多数情况来说可能太长了,很可能会   在一些未知的条件下太短了。

     

文档说:“您的应用程序可以根据需要访问滚动视图   自定义Web视图的滚动行为。“

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (!webView.isLoading) //WEBDIDFINISHLOAD? {
        [webView.scrollView setZoomScale:1.5 animated:YES];
    }
}

看,didFinishLoadMethod是由NSURLConnection的异步通知调用的, 它不一定在主线程中(因为你的UI更新不起作用)

performSelector..after延迟方法很好。延迟甚至没有任何意义, 您只是跳到主线程来进行UI更新并允许 NSURLConnection通知完成。

如果你说afterDelay:0.0

,这可能不重要

这是iOS和OSX中的一种常见情况,您必须弄清楚哪些线程能够更新UI,GCD,NSOperationQueues和后台runLoops在创建的线程上都会使这一点复杂化。

您找到了解决方案,但您需要知道它的含义。在mainThread上调用performSelector,设置一个短延迟并将其固定。