WKWebView
にEstimated Progress
を実装しようとしていますが、理解できないようです。手伝ってくれますか?
ここに私が持っているものがあります:
self.view = self.webView;
NSURL *url = [NSURL URLWithString:stringWeb];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
[self.webView loadRequest:request];
私はこの答えが少し理解できると思いますが、それはスピナーの場合: IWebView with Progress Bar
そしてAppleはある種のestimatedProgress
を文書化します(Safariのように進行状況を示すナビゲーションバーの真下にある薄い青いバーを想定しています)が、一般的には表示されませんそれがどのように実装されるか: https://developer.Apple.com/library/ios/documentation/WebKit/Reference/WKWebView_Ref/#//Apple_ref/occ/instp/WKWebView/estimatedProgress
だから私はここで立ち往生しています。どんな助けでも感謝します、ありがとう!
[〜#〜] update [〜#〜]:これは私が今持っているものです。進行状況ビューとWKWebViewが2回読み込まれているように見えるためクラッシュが発生し、その理由がわかりません。オブザーバーを削除する必要があるエラーを取得します。これが私のコードです-
ViewController.h
@interface WebPageViewController : UIViewController <UIWebViewDelegate>
@property (strong, nonatomic) NSString *stringMobile;
@property (strong, nonatomic) NSString *stringWeb;
@property (strong, nonatomic) IBOutlet UIView *view;
@property (nonatomic, strong) WKWebView *webView;
@property (nonatomic) UIProgressView *progressView;
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
[self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:NULL];
self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
self.progressView.center = self.view.center;
[self.view addSubview:self.progressView];
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:stringWeb]];
[self.webView loadRequest:URLRequest];
}
- (void)dealloc {
[self.webView removeObserver:self forKeyPath:@"estimatedProgress"];
// if you have set either WKWebView delegate also set these to nil here
[self.webView setNavigationDelegate:nil];
[self.webView setUIDelegate:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"estimatedProgress"] && object == self.webView) {
[self.progressView setAlpha:1.0f];
[self.progressView setProgress:self.webView.estimatedProgress animated:YES];
if(self.webView.estimatedProgress >= 1.0f) {
[UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.progressView setAlpha:0.0f];
} completion:^(BOOL finished) {
[self.progressView setProgress:0.0f animated:NO];
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
更新:CocoaPodsを使用すると、これは私が持っているものですが、1つのWebビューではなく2つのビューを表示しています
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *myURL = [NSURL URLWithString: [self.url stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:myURL];
//[self.webView loadRequest:request];
// KIN
// Deleted UIWebView in Storyboard
KINWebBrowserViewController *webBrowser = [[KINWebBrowserViewController alloc] init];
[self.navigationController pushViewController:webBrowser animated:YES];
[webBrowser loadURL:myURL];
}
GitHubで KINWebBrowser を確認して、以下のソリューションの完全な実装を確認してください。
リンクしたestimatedProgress
のWKWebView
プロパティのドキュメントをよく見ると、次のことがわかります。
The WKWebView class is key-value observing (KVO) compliant for this property.
つまり、estimatedProgress
プロパティで監視するキー値を設定して、その値の変化を監視できます。 observeValueForKeyPath
メソッドから、UIを更新できます。
CocoaのKVOデザインパターンはかなり乱雑です。 Key Value Observing のベストプラクティスについては、この優れたNSHipster記事をご覧ください。
estimatedProgress
上のWKWebView
のKVO実装は次のとおりです。
UIViewController
からWKWebView
をセットアップし、estimatedProgress
のオブザーバーとしてselfを追加します
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.webView];
[self.webView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:NSKeyValueObservingOptionNew context:NULL];
同じUIViewController
でobserveValueForKeyPath
メソッドを設定して、estimatedProgress
のwebView
プロパティを除外します。その後、estimatedProgress
値に直接アクセスし、それに応じてUIを更新できます。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.webView) {
NSLog(@"%f", self.webView.estimatedProgress);
// estimatedProgress is a value from 0.0 to 1.0
// Update your UI here accordingly
}
else {
// Make sure to call the superclass's implementation in the else block in case it is also implementing KVO
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
そのUIViewControllerのdeallocメソッドのUIViewController
からKVOを必ず削除してください。オブザーバーがまだ追加されていない場合、クラッシュを防ぐためにisViewLoaded
かどうかを確認することが重要です。
- (void)dealloc {
if ([self isViewLoaded]) {
[self.wkWebView removeObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress))];
}
// if you have set either WKWebView delegate also set these to nil here
[self.wkWebView setNavigationDelegate:nil];
[self.wkWebView setUIDelegate:nil];
}
一部の大きなファイルでこの動作を確認するには、この甘い銀河の巨大な画像ファイルをロードします。 (このファイルは35MBです。WiFiに接続していることを確認してください!)
NSURLRequest *URLRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.spacetelescope.org/static/archives/images/large/opo0328a.jpg"]];
[self.webView loadRequest:URLRequest];
UIProgressView
を使用している場合、次のコードでフェードアウト効果のようなサファリを実現できます。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:NSStringFromSelector(@selector(estimatedProgress))] && object == self.wkWebView) {
[self.progressView setAlpha:1.0f];
[self.progressView setProgress:self.wkWebView.estimatedProgress animated:YES];
if(self.wkWebView.estimatedProgress >= 1.0f) {
[UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.progressView setAlpha:0.0f];
} completion:^(BOOL finished) {
[self.progressView setProgress:0.0f animated:NO];
}];
}
}
else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
スウィフトのような:
@IBOutlet weak var progressView: UIProgressView!
//...
func viewDidLoad() {
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .New, context: nil) // add observer for key path
}
// ...
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if (keyPath == "estimatedProgress") { // listen to changes and updated view
progressView.hidden = webView.estimatedProgress == 1
progressView.setProgress(Float(webView.estimatedProgress), animated: true)
}
}
Swift 3アップデート:
// Add Observer in viewDidLoad
webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?)
{
if (keyPath == "estimatedProgress") { // listen to changes and updated view
progress.isHidden = webView.estimatedProgress == 1
progress.setProgress(Float(webView.estimatedProgress), animated: false)
}
}
Also please make sure to implement "WKNavigationDelegate" and add webview reference navigationDelegate to self like below
webView.navigationDelegate=self
Swift 3.2以上:
private var progressKVOhandle: NSKeyValueObservation?
@IBOutlet weak var progressView: UIProgressView!
// ...
override func viewDidLoad() {
super.viewDidLoad()
// ...
progressKVOhandle = webView.observe(\.estimatedProgress) { [weak self] (object, _) in
self?.progressView.setProgress(Float(object.estimatedProgress), animated: true)
}
}