IOSアプリには、Facebookコメントモジュールを持つドメイン上のWebコンテンツを表示するUIWebViewがあります。コメントモジュールでは、ユーザーがFacebookでサインインしている必要があります。ユーザーがサインインボタンをクリックすると、サインインフローが実行されますが、ページにリダイレクトされることはありません。最終的には、ユーザーに「サインインしました」とだけ伝えるFB所有のページが表示されます。
再現手順:
サインインした後(ステップ3)、認証が成功すると、元のページ(例: http://foo.com/test.htm )にリダイレクトされ、続行できるようになると思います。あなたの相互作用。しかし、これは起こっていません。
代わりに、「あなたは今サインインしています」のような何かを言うだけのFB所有のページにいて、そこに閉じ込められています。リダイレクトは発生しません。
これは確かにバグですか、それともリダイレクトが確実に行われるようにするために他にすべきことはありますか?
IOS 8以降をサポートしているだけの場合は、 WKWebView
を使用できます。これは、 @ kabuko で説明されている機能をすでに実装しています。
// Container view including the main WKWebView
var container : UIView?
var popupWebView : WKWebView?
override func viewDidLoad() {
super.viewDidLoad()
let prefs = WKPreferences()
prefs.javaScriptEnabled = true
// allow facebook to open the login popup
prefs.javaScriptCanOpenWindowsAutomatically = true
let config = WKWebViewConfiguration()
config.preferences = prefs
webView = WKWebView(frame: container.frame, configuration: config)
webView?.UIDelegate = self
webView?.navigationDelegate = self
}
// callback if the content of the webView wants to create a new window
func webView(webView: WKWebView, createWebViewWithConfiguration configuration: WKWebViewConfiguration, forNavigationAction navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
// create new popup webview and add it to the view hierarchy
popupWebView = WKWebView(frame: container.frame, configuration: configuration)
container.addSubview(popupWebView!)
return popupWebView
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
// if the main webView loads a new page (e.g. due to succesful facebook login)
// remove the popup
if (popupWebView != nil) {
popupWebView?.removeFromSuperview()
popupWebView = nil
}
}
他のサイトのFBログイン(Grouponなど)をUIWebView
にロードすると、同様のことが起こるのを見てきました。これが同じ問題である場合(私はそうだと思います)、Facebookが疑わしいようにポップアップでログインウィンドウを開いているため、はです。通常のブラウザでは、ログイン用に別のウィンドウ(ポップアップ)が開かれ、ユーザーがログインすると、そのログインウィンドウが元のウィンドウに戻ってログインしたことを通知します。おそらくEasyXDMなどを使用しています。 。 FlashやpostMessage
など、通信するための戦略にはいくつかの層があるようです。
IOS(およびAndroid)では、これはpostMessage
と通信することになることを意味するはずです。 UIWebView
を通過するURLを追跡すると、最後に次のようなものが表示されます。
_https://s-static.ak.fbcdn.net/connect/xd_proxy.php#<lots of stuff>&relation=opener&transport=postmessage&<lots more stuff>
_
UIWebView
は複数のウィンドウをサポートしていないため、ロードされていないため、元のページにpostMessage
戻ることはできません。できることは、UIWebView
がFBログインページをロードしようとしていることを検出し、それを別のUIWebView
にロードすることです。これで、2つのウィンドウを操作できます。
残念ながら、FBのページのJavaScriptが_window.opener.postMessage
_または_window.parent.postMessage
_を実行しようとすると、_window.parent
_および_window.opener
_がに設定されていないため、これはまだ十分ではありません。適切なウィンドウ。 iOSでこれを行う良い方法がわかりません(対照的にAndroidはこれに適切なAPIを提供します)。
私がこれを回避した方法は、JavaScriptオブジェクトをハックしてこれらの呼び出しをラップすることです。何かのようなもの:
_window.opener={};
window.opener.postMessage = function(data,url) {
// signal your code in objective-c using some strategy
};
window.parent = window.opener;
_
JavaScriptからObjective-Cを呼び出す方法はいくつかあります。 これは公式ドキュメントからのものです 。 _stringByEvaluatingJavaScriptFromString:
_ を使用する前に、このコードを前述の静的FBログインページに挿入できます。これを行うのに適した時間を見つけることができなかったので、ページの読み込み後に挿入し、通常はボディの読み込み時に呼び出される静的ページのFB JavaScriptメソッドであるdoFragmentSend()
を呼び出します。
したがって、必要なのは、UIWebView
を呼び出してこのデータを元のpostMessage
に渡すことだけです。次のようになります。
_NSString *post = [NSString stringWithFormat:@"window.postMessage('%@', '*');", data];
[webView stringByEvaluatingJavaScriptFromString:post];
_
今まで気づかなかった場合、これは非常に厄介なハックであり、他に方法がない限り、おそらくお勧めしませんが、私にとってはうまくいきました。
私も同じ問題を抱えていました。 Facebookにログインした後、UIWebViewコンポーネントが空になった後、その中にhtmlコードがないことがわかりました。 webViewDidFinishLoad関数でUIWebViewコンポーネントのコンテンツを確認し、Facebookログインが白(空の画面)を引き起こすことを検出したときにそのコンテンツをリロードすることで、問題を解決しました。
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if ( [[webView1 stringByEvaluatingJavaScriptFromString:
@"document.body.innerHTML"] isEqualToString:@""] ) {
[webView1 loadRequest:request]; //Define request as you want
}
}
現在モバイルでは、ブラウザはデフォルトで複数のウィンドウをサポートしていません。別の解決策は、「close_popup.php?reload = https://」のようなFacebookからのリダイレクトの成功を監視し、ページをリロードすることです。また、ログインリクエストの前にFacebookのコメント値を保存して、コメントボックスに再度入力できるようにしてください。