WKWebView to handle Social Logins like Facebook, LinkedIn and Google -- iOS (iPhone)



Recently, I have faced one problem while opening sign up/sign in page from web page within iOS app. We have used UIWebView earlier but we were unable to achieve so we have tried WKWebView. I am just describing what steps we have followed to achieve our goal.

First of all, we need to import WebKit framework in class where we want to use it.

#import <WebKit/WebKit.h>

Add various delegates which are required to receive various navigation events and errors.

@interface ViewController : UIViewController <WKNavigationDelegate,
WKUIDelegate,WKScriptMessageHandler>

WKNavigationDelegate -> This protocol can provide methods for tracking progress for main frame navigations and for deciding  policy for  main frame and subframe navigations.

WKUIDelegate -> This protocol provides methods for  presenting native UI on behalf of a web page.

WKScriptMessageHandler -> This protocol provides a  method for receiving messages from JavaScript running in a web page.

Since WKWebView doesn’t yet show up as drag and droppable view in storyboard or Interface builder so we need to create WKWebView Instance programmatically and add it in view.

Create two properties to load web pages one for main web page URL and another is for pop up window for Facebook, LinkedIn or Google sign in page.

@property (strong,nonatomic) WKWebView *webView;
@property (strong,nonatomic) WKWebView *popWindow;


Put below source code in your viewDidLoad.

NSURL *url = [NSURL URLWithString:@"http://your web page"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
WKPreferences *thisPref = [[WKPreferences alloc] init];
thisPref.javaScriptCanOpenWindowsAutomatically = YES;
thisPref.javaScriptEnabled = YES;
theConfiguration.preferences = thisPref;
_webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:theConfiguration];
[_webView loadRequest:request];
[_webView setBackgroundColor:[UIColor clearColor]];
[self.view setBackgroundColor:[UIColor whiteColor]];
[self.view addSubview:_webView];


Below function helps to create WKWebView pop up or new window for social logins.

-(WKWebView *) getPopwindow:(WKWebViewConfiguration*) configuration {
    WKWebView* webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
    webView.frame = CGRectMake(self.view.frame.origin.x,self.view.frame.origin.y, self.view.frame.size.width,       
        self.view.frame.size.height);
    webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    return webView;
}


This function helps to dismiss or remove pop up window.

-(void) dismissPopWindow:(WKWebView*) webView {
    NSString *url = webView.URL.host.lowercaseString;
    if ((_popWindow != nil && [url containsString:HostPrefix]) || (_popWindow != nil && [url 
            containsString:LINKEDIN_HOST])) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (_popWindow != nil){
                [_popWindow removeFromSuperview];
                _popWindow = nil;
            }
        });
    }
}


Now add various delegates methods or message handlers. Communication from web to app has improved significantly with these message handlers.

# pragma mark WKUIDelegate
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
    _popWindow = [self getPopwindow:configuration];// It will open new window
    _popWindow.navigationDelegate = self;
    [self.view addSubview:_popWindow];
    return _popWindow;
}

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"%@", message);
}

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"%s", __FUNCTION__);
}

- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"%s", __FUNCTION__);
    // You can inject java script here if required as below
    //NSString *javascript = @"var meta = document.createElement('meta');meta.setAttribute('name', 'viewport');meta.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no');document.getElementsByTagName('head')[0].appendChild(meta);";
    //[webView evaluateJavaScript:javascript completionHandler:nil];
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"%s", __FUNCTION__);
}

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"%s", __FUNCTION__);
    [[[UIAlertView alloc] initWithTitle:@"Network Error"
                          message:NWServerErrorMessage
                          delegate:nil
                          cancelButtonTitle:NSLocalizedString(@"OK", nil)
                          otherButtonTitles:nil, nil] show];
}

- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"%s", __FUNCTION__);
    NSLog(@"%@",webView.URL.absoluteString.lowercaseString);
    [self dismissPopWindow:webView];
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    [self dismissPopWindow:webView];
    decisionHandler(WKNavigationActionPolicyAllow);
}

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
    decisionHandler(WKNavigationResponsePolicyAllow);
}


Just run the app and you will get the expected outcome.

WKWebView inherits much of the same programming interface as UIWebVIew, making it convenient for apps to WKWebKit. Only one condition, WebKit has support for iOS 8 and above.

WKWebView has higher performance compared to UIWebView. WKWebView API has the same performance as Safari App, which has the Nitro JavaScript Engine.


덧글

댓글 입력 영역