您好我是编程的新手,我正在尝试在Xcode上制作我的第一个iPhone应用程序。
我的应用程序包含一个按钮,可在按下时打开UIWebView并加载主页。
现在我还想在Safari也使用的WebView中添加一个Progress View,它表示加载页面的进度。我怎么能这样做?
到目前为止,我的代码用于在UIWebView中加载URL:
·H
IBOutlet UIWebView *webView;
的.m
- (void)viewDidLoad
{
[webView loadRequest:[NSURLRequest requestWithURL: [NSURL URLWithString:@"http:/www.google.com/"]]];
感谢您的帮助!
答案 0 :(得分:70)
要获得准确的UIProgressView
,您需要执行以下任务:
现在当你加载UIWebView
时,那是不可能的。苹果公司也没有做到这一点。 Apple经常使用假的UIProgressView
来为您提供在页面加载时要查看的内容。 Mail还使用虚假进度视图。去试试吧。这就是Apple的虚假进展观点的工作方式:
要实现此目的,您必须手动设置progressView的动画。你可以将它子类化,但这对你来说可能有点先进。最简单的方法是:
在myViewController.h中
@interface myViewController : UIViewController {
BOOL theBool;
//IBOutlet means you can place the progressView in Interface Builder and connect it to your code
IBOutlet UIProgressView* myProgressView;
NSTimer *myTimer;
}
@end
在myViewController.m
中#import "myViewController.h"
@implementation myViewController
- (void)webViewDidStartLoad:(UIWebView *)webView{
myProgressView.progress = 0;
theBool = false;
//0.01667 is roughly 1/60, so it will update at 60 FPS
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.01667 target:self selector:@selector(timerCallback) userInfo:nil repeats:YES];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
theBool = true;
}
-(void)timerCallback {
if (theBool) {
if (myProgressView.progress >= 1) {
myProgressView.hidden = true;
[myTimer invalidate];
}
else {
myProgressView.progress += 0.1;
}
}
else {
myProgressView.progress += 0.05;
if (myProgressView.progress >= 0.95) {
myProgressView.progress = 0.95;
}
}
}
@end
然后,在您的任务完成的位置,设置theBool = true;
,进度视图将自行处理。更改if语句中的值以控制动画的速度。
答案 1 :(得分:5)
Swift 2.2
class ViewController: UIViewController,UIWebViewDelegate {
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var myProgressView: UIProgressView!
var myTimer = NSTimer()
var theBool = Bool()
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "https://www.youtube.com")
let request = NSURLRequest(URL: url!)
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
webView.loadRequest(request)
}
func timerCallback(){
if theBool {
if myProgressView.progress >= 1 {
myProgressView.hidden = true
myTimer.invalidate()
}else{
myProgressView.progress += 0.1
}
}else{
myProgressView.progress += 0.05
if myProgressView.progress >= 0.95 {
myProgressView.progress = 0.95
}
}
}
func webViewDidStartLoad(webView: UIWebView) {
activityIndicator.startAnimating()
myProgressView.progress = 0
theBool = false
myTimer = NSTimer.scheduledTimerWithTimeInterval(0.01667,target: self,selector: #selector(ViewController.timerCallback),userInfo: nil,repeats: true)
}
func webViewDidFinishLoad(webView: UIWebView) {
activityIndicator.stopAnimating()
theBool = true
}
}
答案 2 :(得分:3)
我按照Wolflink的回答,发现同样的问题没有使用progressView动画。
阅读NSTimer类参考:
在讨论中,您可以阅读: “您必须使用addTimer:forMode:”将新计时器添加到运行循环中。“
所以我添加了
[[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
后
myTimer = [NSTimer timerWithTimeInterval:0.01667 target:self selector:@selector(timerCallback) userInfo:nil repeats:YES];
它对我有用(正如WolfLink推荐的那样,我做了子类UIProgressView)
答案 3 :(得分:3)
如果有人想在swift 3中做到这一点,我花了几天时间试图找出它并最终做到了。
以下是代码:)
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "http://google.com")
let request = NSURLRequest(url: url as! URL)
webView.loadRequest(request as URLRequest)
webView.delegate=self
}
func webViewDidStartLoad(_ webView: UIWebView) {
self.progressView.setProgress(0.1, animated: false)
}
func webViewDidFinishLoad(_ webView: UIWebView) {
self.progressView.setProgress(1.0, animated: true)
}
func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
self.progressView.setProgress(1.0, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
答案 4 :(得分:2)
很难(如果可能的话),因为您必须跟踪网站加载的所有资源,但是......
我有一个想法。它比真正的解决方案更像是一个技巧,但我认为即使Apple在消息应用程序中使用它:)
我想我们都知道,这就是消息应用程序的工作原理,因为我不相信能够以如此准确的进度跟踪发送短信:)
答案 5 :(得分:0)
我会添加评论,而不是添加答案,但我还没有足够的声誉来发表评论!
仅在几天前,我几乎问了同样的问题。在那个问题中,我提出了我想出的解决方案。我的解决方案比WolfLink更复杂,但它确实跟踪加载页面的真实进度,尽管它不是100%准确。正如WolfLink所说,这是不可能的。我的问题可以在这里找到:Progress bar for UIWebView
请注意,无论您采用哪种方式,都需要检查UIWebView的加载属性,以确定何时完成页面加载。
答案 6 :(得分:0)
Apple现在提供WebKit框架,其中包括WKWebView类,它允许您使用属性“估计进度”查询估计的进度,因此您不再需要假冒'像在UIWebView上显示进度条一样的进展。
答案 7 :(得分:0)
我尝试了以下模式。它给了我更好的结果。我正在使用WKWebview。
@IBOutlet weak var progressView: UIProgressView! // added in storyboard
@IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupEstimatedProgressObserver()
}
// Observe the WebViewClient for estimatedProgress value
private func setupEstimatedProgressObserver() {
estimatedProgressObserver = webView.observe(\.estimatedProgress, options: [.new]) { [weak self] webView, _ in
self?.progressView.progress = Float(webView.estimatedProgress)
}
}
//When WebView load finished in WKNavigationDelegate in didFinish method we will use the following approach
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
self.progressView.progress = 1.0
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
// your code here
self.progressView.isHidden = true
}
}
答案 8 :(得分:0)
这里的一些答案并不完全正确,因为它们忘记为Webview注册代表。不幸的是,实现UIWebViewDelegate并覆盖这两个方法是不够的。 您还必须将网络视图的委托设置为self 。
class ViewController: UIViewController,UIWebViewDelegate {
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var myProgressView: UIProgressView!
var myTimer = NSTimer()
var theBool = Bool()
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "https://www.youtube.com")
let request = NSURLRequest(URL: url!)
activityIndicator.hidesWhenStopped = true
activityIndicator.startAnimating()
// !
webView.delegate = self // <--- important
// !
webView.loadRequest(request)
}
func timerCallback(){
if theBool {
if myProgressView.progress >= 1 {
myProgressView.hidden = true
myTimer.invalidate()
}else{
myProgressView.progress += 0.1
}
}else{
myProgressView.progress += 0.05
if myProgressView.progress >= 0.95 {
myProgressView.progress = 0.95
}
}
}
func webViewDidStartLoad(webView: UIWebView) {
activityIndicator.startAnimating()
myProgressView.progress = 0
theBool = false
myTimer = NSTimer.scheduledTimerWithTimeInterval(0.01667,target: self,selector: #selector(ViewController.timerCallback),userInfo: nil,repeats: true)
}
func webViewDidFinishLoad(webView: UIWebView) {
activityIndicator.stopAnimating()
theBool = true
}
}
此代码指的是答案@ ZAFAR007