UIWebViewDelegate:页面内导航期间未调用 webViewDidFinishLoad
Posted
技术标签:
【中文标题】UIWebViewDelegate:页面内导航期间未调用 webViewDidFinishLoad【英文标题】:UIWebViewDelegate: webViewDidFinishLoad not called during in-page navigation 【发布时间】:2013-03-17 06:36:35 【问题描述】:我有一个应用程序,用户可以在其中浏览一堆本地存储的 HTML 文件。我有一个UIWebView
,使用UIWebViewDelegate
正确配置。通常,当用户点击链接时,会调用shouldStartLoadWithRequest
,稍后再调用webViewDidFinishLoad
。
但是,如果链接指向与当前显示的页面相同的页面上的锚点,则仅调用 shouldStartLoadWithRequest
。 webViewDidFinishLoad
不会触发。
从某种意义上说,我认为这可能是预期的行为,因为页面内导航不需要重新加载页面。但是,页面内导航完成后,我真的需要一个地方来挂钩调用堆栈。最佳解决方案会在任何类型的导航结束时通知我,无论是从另一个页面、页内操作还是前进/后退操作。
到目前为止,我最好的解决方法是在我的 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”shouldStartLoadWithRequest
returns 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