How can I get UIWebView to open Facebook login page in response to the OAuth request on iOS 5 and iOS 6?

后端 未结 5 1309
Happy的楠姐
Happy的楠姐 2020-12-15 13:30

We have:
(1) Facebook API-based web application with Facebook OAuth functionality (“the FB web app”)
(2) UIWebView-based browser on iPad (“the Browser”

5条回答
  •  渐次进展
    2020-12-15 14:08

    In case anyone is googling, here's what worked for me:

    -(BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)inType {
        if ([request.URL.absoluteString containsString:@"m.facebook.com"]) {
            if ([request.URL.absoluteString rangeOfString:@"back"].location == 0) {
                [self.popUp removeFromSuperview];
                self.popUp = nil;
                return NO;
            }
            if (self.popUp) {
                return YES;
            }
    
            UIWebView *wv = [self popUpWebView];
            [wv loadRequest:request];
            return NO;
        }
        return YES;
    }
    
    - (UIWebView *) popUpWebView {
        toolbar height
        UIWebView *webView = [[UIWebView alloc]
                initWithFrame:CGRectMake(0, 0, (float)self.view.bounds.size.width,
                        (float)self.view.bounds.size.height)];
        webView.scalesPageToFit = YES;
        webView.delegate = self;
        // Add to windows array and make active window
        self.popUp = webView;
        [self.view addSubview:webView];
        return webView;
    }
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView {
    
        if (self.popUp) {
            NSError *error = nil;
            NSString *jsFromFile = @"window.close=function(){window.location.assign('back://' + window.location);};";
            __unused NSString *jsOverrides = [webView
                    stringByEvaluatingJavaScriptFromString:jsFromFile];
    
            JSContext *openerContext = [self.webView
                    valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
            JSContext *popupContext = [webView
                    valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
            popupContext[@"window"][@"opener"] = openerContext[@"window"];
        }
    
    
      //this is the secret sauce  
      if (webView == self.popUp
                && [webView.request.URL.absoluteString containsString:@"m.facebook.com"]
                && [[webView stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML"] isEqualToString:@""]) {
            [webView stringByEvaluatingJavaScriptFromString:@"eval(document.getElementsByTagName('script')[0].text)"];
        }
    }
    

    I snagged a bunch of this implementation from here.

    Depending on your web implementation, there will likely be one extra step. The Facebook script actually executes a window.close() then a window.open() then a window.close(). For me this was causing problems because on the web side, after this login is complete, my window (i.e. for the webView that I want the user to log in to) was getting a window.close() call, coming from the Facebook SDK. I'm assuming this is because the Facebook SDK expects that window.open() call to open a new window that it will close.

    Since we didn't override the functionality of window.open(), calling window.open() won't do anything, and the Facebook SDK will attempt to close your window. This could cause all kind of problems, but for me since I'm using Parse, window.localStorage was set to null so I was getting all kinds of errors.

    If something like this is happening for you, you have two options to fix it:

    1. If you have control of the web code, and your down for a small hack, throw this in window.close=function(){}
    2. If you don't have control of the web code, you can either add an override to window.close for the main webView like we did for the popUp webView, or override the window.open function to open another popUp (which is described in more detail here)

提交回复
热议问题