【问题标题】:Loading UIWebView From Background Fetch从后台获取加载 UIWebView
【发布时间】:2014-07-02 02:04:00
【问题描述】:

我在我的应用程序中使用 UIWebView 来加载网站的内容。然后我使用javascript登录网站,然后在我登录后解析页面的内容以获取我需要的数据。我每 5 分钟执行一次,这在前台运行良好。但是,当我后台应用程序时,我调用了包含 UIWebView 的 UIViewController 并点击了将 URL 加载到 UIWebView 中的方法,但之后没有任何反应。

我很确定 UIViewController 必须处于活动状态才能更新 UIWebView,但是有没有办法解决这个问题?在后台检查这些数据确实是应用程序的重点。

编辑

jakepeterson - 根据您的代码,我尝试从 Swift 开始子类化 UIWebView。这是据我所知:

    class CustomWebView: UIWebView, UIWebViewDelegate
{
    var webView: UIWebView
    var requestURL: NSURL
    var urlRequest: NSURLRequest

    init()
    {
        webView = UIWebView()
        requestURL = NSURL(string: "http://www.google.com")
        urlRequest = NSURLRequest(URL: requestURL)

        super.init(frame: CGRectMake(0, 0, 100, 100))
        webView.delegate = self
        webView.addSubview(webView.window)
        webView.loadRequest(request)
    }

    func webViewDidFinishLoad(sender: UIWebViewDelegate)
    {
        //Do stuff
    }
}

我仍然没有点击 webViewDidFinishLoad 委托方法。我认为这可能与这条线有关:

webView.addSubview(webView.window)

在您的代码中,您有 self.view 但这并没有显示为可用选项。

更新

这是我现在正在做的事情,并且代表现在被触发了:

import UIKit

class CustomWebView: UIWebView
{
    var uiView = UIView()

    init(frame: CGRect)
    {
        super.init(frame: frame)
        self.delegate = self
    }

    convenience init(frame:CGRect, request:NSURLRequest)
    {
        self.init(frame: frame)
        uiView.addSubview(self)
        loadRequest(request)
    }    
}

extension CustomWebView: UIWebViewDelegate
{
    func webViewDidStartLoad(webView: UIWebView!)
    {
        println("webViewDidStartLoad")
    }

    func webViewDidFinishLoad(webView: UIWebView)
    {
        println("webViewDidFinishLoad")
    }

    func webView(webView: UIWebView!, didFailLoadWithError error: NSError!)
    {
        println("An error occurred while loading the webview")
    }
}

【问题讨论】:

    标签: ios uiwebview swift


    【解决方案1】:

    下面是一个示例,说明如何客观地将 UIWebView 类与异步逻辑一起使用:

    - (id)init
    {
        self = [super init];
        if (self)
        {
            self.webView = [[UIWebView alloc] init];
            self.webView.delegate = self;
            [self.view addSubview:self.webView];
    
            self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
            [self.view addSubview:self.activityIndicator];
        }
    
        return self;
    }
    
    - (id)initWithUrl:(NSURL *)url
    {
        self = [self init];
        if (self)
        {
            NSURLRequest *request = [NSURLRequest requestWithURL:url];
            [self.webView loadRequest:request];
            [self.activityIndicator startAnimating];
        }
    
        return self;
    }
    
    #pragma mark - UIWebViewDelegate
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        [self.activityIndicator stopAnimating];
    }
    
    - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    {
        [self.activityIndicator stopAnimating];
    
        NSLog(@"An error occurred while loading. (error: %@)", error);
    
        // Alert the user
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:@"Dude... we messed up. This web page can't be loaded at this time." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];
    }
    

    为什么会这样?

    因为您依赖UIWebViewDelegate 的委托方法来告诉您UIWebView 何时完成加载。我将错误委托方法作为奖励包括在内。

    这里的例子是使用一个UIActivityIndicatorView 类,它是为异步任务设计的。通过遵循相同的实现风格,您可以将activityIndicator 替换为您计划对UIWebView 的结果采取实际行动的几乎任何东西。

    祝你好运

    更新

    斯威夫特完全是另一种野兽。你的 swift 类有很多错误。这就是我将如何用 Swift 重写我最初在 ObjC 中给你的内容:

    import UIKit
    
    class CustomWebView: UIWebView {
    
        var activityIndicator:UIActivityIndicatorView
    
        init(frame: CGRect) {
            self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
            super.init(frame: frame)
            self.delegate = self
        }
    
        convenience init(frame:CGRect, request:NSURLRequest) {
            self.init(frame: frame)
            loadRequest(request)
        }
    
    }
    
    extension CustomWebView: UIWebViewDelegate {
    
        func webViewDidFinishLoad(webView: UIWebView) {
            self.activityIndicator.stopAnimating()
        }
    
        func webView(webView: UIWebView!, didFailLoadWithError error: NSError!) {
            self.activityIndicator.stopAnimating()
    
            println("An error occurred while loading the webview")
        }
    
    }
    

    【讨论】:

    • 这对我不起作用。我编辑了我的原始帖子以解释我所看到的。
    • 感谢您将其转换为 Swift。它帮助我更好地理解了你在做什么。当我运行您的代码时,虽然我无法设置 NSURLRequest。每次我尝试用一​​个初始化它时,“self.request = newValue”行都会出现“EXC_BAD_ACCESS”错误。
    • 我是个新手,所以请耐心等待我尝试调试。我在设置 NSURLRequest 的位置添加了“println(”(newValue)“) 行。我在控制台窗口中得到了这个:“ { URL:google.com, headers: (null) }”。我得到了数百次。所以我想知道它是否会因为某种原因陷入循环并耗尽内存......
    • 好的,它不再崩溃,但现在我回到了我原来的问题,即委托事件永远不会触发,特别是 webViewDidFinishLoad 事件。
    • 您是否在初始化程序中传递了一个非零请求?
    【解决方案2】:

    看来,我发现的将控件添加到 UIView 以使委托触发的技巧仅在前台有效。因此,对于任何检查此问题的人来说,目前似乎没有办法在后台执行此操作。

    【讨论】:

    • WKWebView 也是这样吗?
    猜你喜欢
    • 2013-11-10
    • 2015-12-13
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多