UIWebView的进度条(和网络活动状态)

时间:2014-01-19 23:43:41

标签: ios uiwebview uiwebviewdelegate

经过长时间休息后,我又开始进行ios开发了。考虑到这一点,我下载了最新版本的XCode(5.02)并开始编写以ios7为目标的应用程序。在我向我的应用添加“webView页面”之前,一切都很顺利。我天真地期待UIWebView像Safari中的页面一样工作,但事实并非如此。最缺少的是在页面加载时对用户完全没有反馈。即网络活动指示器根本不显示,并且在页面加载时没有显示进度条。所以我想你只需要手动添加它们。这不应该太难,不是吗?

几天后,我的工作得很好,但我对结果并不满意。我花了相当多的调试和实验来获得我现在的位置。我想我的问题是“有什么办法可以改善我的方法吗?”而且,也许,“我应该向Apple报告加载和请求财产问题并要求他们修复它们吗?”

最初我在互联网上查找了这个问题的解决方案,关于它的stackoverflow有很多问题,但似乎没有人真正破解它。一些建议的方法:

  1. 使用私有UIWebView API(如果您想将应用程序发布到商店,则无济于事)
  2. 使用NSURLConnection下载页面(仅提供初始页面下载的进度)
  3. 使用第三方库下载和处理页面(大锤要破解坚果?)
  4. 使用UIWebViewDelegate并跟踪负载开始和结束
  5. 使用UIWebViewDelegate手动显示和隐藏网络活动指示器
  6. 最后我决定使用4.和5.但这很棘手,因为:

    1. 开始和结束通话可以按任意顺序进行
    2. 有些请求已启动,但从未完成
    3. 部分请求已完成,但出现错误
    4. 第一个问题可以通过计算开始和结束来确定,确保计算的进度百分比仅增加,并且只在最后一个请求完成时关闭网络指示器。

      第二个问题更难以解决。 UIWebView有两个原则上可用于执行此操作的属性(加载和请求),但它们似乎以神秘的方式工作。我在这里找到的一些答案和评论表明,loading属性永远不会更新,但请求就是。这最初对我有意义,因为页面永远不会真正停止加载(它们可能具有动态内容),因此有意义的是加载属性只会告诉您Web视图是否正在主动加载内容(即,如果已调用loadRequest并且stopLoading还没有“T)。

      然而,至少在ios7上,它实际上是以相反的方式工作。 request属性永远不会更新,因此您无法使用request属性来确定视图是否已完成加载所有内容(即通过检查已完成的请求是否为初始请求)。虽然loading属性已更新,但在页面完全加载时它确实设置为NO。这有很大帮助,但我注意到动态内容(例如页面广告)会导致加载重置为YES,因此处理它仍然有点棘手。

      第三个问题不是问题,除了我观察到webView内部:didFailLoadWithError,loading属性总是设置为NO。但是,这似乎是一个临时状态,如果您愿意,可以忽略错误并等待在webViewDidFinishLoad中将加载设置为NO。由于请求属性未更新,因此无法知道它是否是失败的初始请求或其中一个子请求(您可能会或可能不关心)。所以我决定采用一种允许程序员选择他们想要的行为的解决方案。

      如果出现以下情况会更容易:

      1. 请求属性已更新(或传入当前请求,就像在webView中一样:shouldStartLoadWithRequest:navigationType)
      2. 在webView中正确设置了loading属性:didFailLoadWithError
      3. 这是我在webView的视图控制器中的代码:

        - (void)resetProgress {
            framesToLoad = 0;
            framesLoaded = 0;
            currentProgress = 0.0f;
        }
        
        - (void)resetForNewPage {
            // Reset progress
            [self resetProgress];
        
            // Monitor the page load
            monitorProgress = YES;
        
            // Keep going if errors occur
            // completeIfError = NO;
        
            // Stop updates if an error occurs
            completeIfError = YES;
        }
        
        - (void)webViewLoaded {
            [self resetProgress];
            [entryProgressView setProgress: 0.0f animated: YES];
        }
        
        - (void)viewDidLoad {
            [super viewDidLoad];
        
            // Reset state for new page load
            [self resetForNewPage];
        
            // Load the page
            NSURLRequest *entryRequest = [NSURLRequest requestWithURL:entryURL];
            [entryWebView loadRequest:entryRequest];
        }
        
        -(void)viewWillDisappear:(BOOL)animated {
            [entryWebView stopLoading];
        
            entryWebView.delegate = nil;
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        }
        
        - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
            if (navigationType == UIWebViewNavigationTypeLinkClicked) {
                // Reset state for new page load
                [self resetForNewPage];
            }
        
            return YES;
        }
        
        -(void)webViewDidStartLoad:(UIWebView *)webView {
            [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
            if (!monitorProgress) {
                return;
            }
        
            // Increment frames to load counter
            framesToLoad++;
        }
        
        -(void)webViewDidFinishLoad:(UIWebView *) webView {
            if (!monitorProgress) {
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                return;
            }
        
            // Increment frames loaded counter
            framesLoaded++;
        
            // Update progress display
            float newProgress = ((float) framesLoaded) / framesToLoad;
            if (newProgress > currentProgress) {
                currentProgress = newProgress;
                [entryProgressView setProgress: newProgress animated: YES];
            }
        
            // Finish progress updates if loading is complete
            if (!webView.loading) {
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                monitorProgress = NO;
        
                [entryProgressView setProgress: 1.0 animated: YES];
                [self performSelector:@selector(webViewLoaded) withObject: nil afterDelay: 1.0];
            }
        }
        
        - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
            if (!monitorProgress) {
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                return;
            }
        
            // Increment frames loaded counter
            framesLoaded++;
        
            // Update progress display
            float newProgress = ((float) framesLoaded) / framesToLoad;
            if (newProgress > currentProgress) {
                currentProgress = newProgress;
                [entryProgressView setProgress: newProgress animated: YES];
            }
        
            // Finish progress updates if required
            if (completeIfError) {
                [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
                monitorProgress = NO;
        
                [entryProgressView setProgress: 1.0 animated: YES];
                [self performSelector:@selector(webViewLoaded) withObject: nil afterDelay: 1.0];
            }
        }
        

0 个答案:

没有答案