简体   繁体   中英

iOS how can I add a completion block to UIWebView loadRequest:?

I'm working with a UIWebView and am already using webViewDidFinishLoad: method with an optional block that gets executed after loading complete:

    -(void)webViewDidFinishLoad:(UIWebView *)webView
    {
        [super webViewDidFinishLoad:webView];

//... bunch of other code        

        if(self.webViewFinishLoadBlock != nil)
        {
            self.webViewFinishLoadBlock();
        }
    }

Now I'm working with an even more complicated sequence of loading pages and redirects that makes the logic above not sufficient. I don't want to register myself as a delegate of dummyWebView and have to juggle multiple completion blocks stored in my view controller's properties:

    dummyWebView = [[UIWebView alloc] initWithFrame:CGRectZero];
    [dummyWebView loadRequest:[NSURLRequest requestWithURL:logoutURL]];
//Ideally here I would know when dummyWebView finishes loading, because there's some code I want to execute once it is done

My question is:

Is there some kind of third party framework that would allow me to use loadRequest:withCompletion: to simplify writing callback code?

You can just:

  • Subclass UIWebView with a property to hold the webViewDidFinish completion block;

  • Make sure it specifies its delegate;

  • Implement the webViewDidFinish much like you wrote it (though I'd suggest the block return both the web view as well as the NSError object, if any); and

  • Implement the webView:didFailLoadWithError: , too.

Thus:

//  MyWebView.h

#import <UIKit/UIKit.h>

typedef void(^WebViewFinishLoadBlock)(UIWebView *, NSError *);

@interface MyWebView : UIWebView

@property(nonatomic, copy) WebViewFinishLoadBlock webViewFinishLoadBlock;

- (void)loadRequest:(NSURLRequest *)request withCompletionHandler:(WebViewFinishLoadBlock)completionHandler;

@end

And

//  MyWebView.m

#import "MyWebView.h"

@interface MyWebView () <UIWebViewDelegate>
@end

@implementation MyWebView

- (void)loadRequest:(NSURLRequest *)request withCompletionHandler:(WebViewFinishLoadBlock)completionHandler
{
    self.delegate = self;
    self.webViewFinishLoadBlock = completionHandler;

    [self loadRequest:request];
}

#pragma mark - UIWebViewDelegate

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    if (self.webViewFinishLoadBlock) {
        self.webViewFinishLoadBlock(webView, nil);
        self.webViewFinishLoadBlock = nil;
    }
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    if (self.webViewFinishLoadBlock) {
        self.webViewFinishLoadBlock(webView, error);
        self.webViewFinishLoadBlock = nil;
    }
}

@end

And then:

MyWebView *webView = [[MyWebView alloc] init];
webView.frame = self.view.bounds;
[self.view addSubview:webView];

NSURLRequest *request = [NSURLRequest requestWithURL:url];
[webView loadRequest:request withCompletionHandler:^(UIWebView *webView, NSError *error) {
    if (error) {
        NSLog(@"failed: %@", error);
    } else {
        NSLog(@"succeeded");
    }
}];
- (void)webViewDidFinishLoad:(UIWebView *)webView

is a delegate method. By convention delegate methods require the object pass itself back to the delegate:

(UIWebView*)webView

Through a parameter.

If we want to get last request parameter using property request: that means webView.request.URL

The parent object can be the delegate for multiple objects, and it can identify which it is getting a response from though that parameter. Either switch on what responds to you or build some infrastructure to handle it more elegantly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM