UIWebViewDelegate:页面内导航期间未调用 webViewDidFinishLoad

Posted

技术标签:

【中文标题】UIWebViewDelegate:页面内导航期间未调用 webViewDidFinishLoad【英文标题】:UIWebViewDelegate: webViewDidFinishLoad not called during in-page navigation 【发布时间】:2013-03-17 06:36:35 【问题描述】:

我有一个应用程序,用户可以在其中浏览一堆本地存储的 HTML 文件。我有一个UIWebView,使用UIWebViewDelegate 正确配置。通常,当用户点击链接时,会调用shouldStartLoadWithRequest,稍后再调用webViewDidFinishLoad

但是,如果链接指向与当前显示的页面相同的页面上的锚点,则仅调用 shouldStartLoadWithRequestwebViewDidFinishLoad 不会触发。

从某种意义上说,我认为这可能是预期的行为,因为页面内导航不需要重新加载页面。但是,页面内导航完成后,我真的需要一个地方来挂钩调用堆栈。最佳解决方案会在任何类型的导航结束时通知我,无论是从另一个页面、页内操作还是前进/后退操作。

到目前为止,我最好的解决方法是在我的 shouldStartLoadWithRequest 方法结束时调用 performSelector: withObject: afterDelay:,但我对此并不满意。

有谁知道我该如何正确解决这个问题?任何见解都值得赞赏!

【问题讨论】:

我没有看到任何锚点点击都调用了 shouldStartLoadWithRequest,只有整页加载。我很好奇这种行为是否已经改变,或者如果没有,我一定是做错了什么。 【参考方案1】:

您可以尝试使用NSURLConnectionDataDelegate,它可以让您处理传入的数据。也许您可以通过在 html 文件中添加符号来确定页面是否是手动加载的。

NSURLConnectionDataDelegate Reference

编辑:gist.github.com/buranmert/7304047我写了一段代码,它工作了,这可能不是你想要的工作方式,但也许它有帮助。每次用户单击带有锚点的 URL 时,它都会创建另一个连接,并在连接完成加载 Web 视图时加载数据,这标志着 Web 视图完成加载页面的点。由于您仅使用本地 html 文件,我认为创建连接不会产生问题

【讨论】:

感谢您的回答!在我的情况下,NSURLConnectionDataDelegate 上似乎具有任何潜力的唯一方法是connectionDidFinishLoading。阅读方法描述,听起来不太有希望,因为页面内导航是否会触发加载是值得怀疑的。不过,我会试一试。 耶!我得到了这个工作!到目前为止,我认为这里建议的最佳解决方案。非常感谢您花时间帮助我。赏金是你的,好先生! 实际上,webView.renderingFinished 上的回调/挂钩本来是 100% 完美的,但这已经足够接近了。 是的,我首先想到的是,它会是解决方案,这更像是一种解决方法。很高兴它对你有所帮助,伙计 这个解决方案的另一个很酷的地方是UIWebViewNavigationTypeBackForward 会显示是否使用了后退/前进按钮。【参考方案2】:

您所描述的是预期行为。正如 AJAX 或资源请求永远不会传递给委托一样,只有根页面更改才会到达webViewDidFinishLoad:。但我有一个好消息,这并不涉及在汽车保险上节省一大笔钱。

在 iFrame DO 中执行的加载会触发完整的委托方法,这为您提供了解决方案。您可以使用此机制向本机代码发布通知,就像console.log() 所描述的in this post 一样。或者,Native Bridge 可以很好地从 javascript 调用您的 Objective C 代码。

【讨论】:

+1 我相信这会奏效,但与 Mert Buran 的 ios 式建议相比,它感觉更像是一种 hack。不过,非常感谢您的帮助!【参考方案3】:

只要检查一下天气你得到了委托函数 DidStartLoading 如果它被调用,毫无疑问 DidFinish 也应该被调用

【讨论】:

不,在页面内导航中不会调用 URL 上的片段。 检查天气 webView:shouldStartLoadWithRequest:navigationType: 返回“NO”,另一种可能是 webview 委托设置为“nil” shouldStartLoadWithRequestreturns YES 并且代理设置正确。事实上,这是我提出问题的前提。 检查天气函数调用来委托 shouldStartLoadWithRequest 并且天气 webview 正在加载页面。如果一切都很好,那么如果可能的话,发布 ht ecode sn-p 以便我可以检查。【参考方案4】:

你确定你的 shouldStartLoadWithRequest 总是返回 YES???

我总是加

return YES;

shouldStartLoadWithRequest 实施结束时。这对我有用。 通过返回 YES,它表示 webview 已经加载并会调用 webViewDidFinishLoad

【讨论】:

【参考方案5】:
if([webView isLoading]==1)

    //your webview is loading

else

   //your webview has loaded

【讨论】:

是的,但是轮询 webView 的加载状态不是操作系统回调/挂钩,而是相反。【参考方案6】:

这是 Mert Buran 代码的 Swift 实现,以防万一有人在寻找它。 (虽然 NSURLConnection 自 iOS 9 起已弃用)

但这并不能解决我的问题。当我单击弹出视频的 jquery 链接时,它不会触发 webViewDidFinishLoad。

class WebViewController: UIViewController, UIWebViewDelegate, NSURLConnectionDelegate 

var menuURL: String?

var response: NSURLResponse?
var data = NSData()

// MARK: Properties
@IBOutlet weak var webView: UIWebView!

override func viewDidLoad() 
    super.viewDidLoad()

    webView.delegate = self

    // From Web
    let url = NSURL (string: menuURL!)
    let urlRequest = NSURLRequest(URL: url!)

    let connection = NSURLConnection(request: urlRequest, delegate: self)
    self.data = NSData()
    connection!.start()

    // if this is false, page will be 'zoomed in' to normal size
    webView.scalesPageToFit = false



func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool 
    if navigationType == .LinkClicked && request.URL!.fragment != nil 
        let connection = NSURLConnection(request: request, delegate: self)
        connection!.start()
        return false
    
    return true


func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) 
    self.response = response


func connection(connection: NSURLConnection, didReceiveData data: NSData) 
    let oldData = NSMutableData(data: self.data)
    oldData.appendData(data)
    self.data = oldData


func connectionDidFinishLoading(connection: NSURLConnection) 
    self.webView.loadData(self.data, MIMEType: self.response!.MIMEType!, textEncodingName: "utf-8", baseURL: self.response!.URL!)
    self.data = NSData()




【讨论】:

以上是关于UIWebViewDelegate:页面内导航期间未调用 webViewDidFinishLoad的主要内容,如果未能解决你的问题,请参考以下文章

如何从子框架导航父框架

导航期间的 Codeigniter 'GET' 错误 404

导航期间内存增加,但堆看起来不错?

UIWebViewDelegate DidFinishLoad 未在自定义类中触发 (Swift)

使用底部导航栏颤动保存 PageView 内每个页面的状态

Win10系列:JavaScript页面导航