iOS:Facebook评论插件移动不断重新加载

最近我一直试图将Facebook社交插件整合到iOS中的自定义UIWebView中,以评论网页。 我已经添加了Likebutton以及Comments插件。 以下是我加载到Web视图中的HTML代码:

<html> <body> <div id="fb-root"></div> <script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script> <div class="fb-like" data-href="http://www.heretheweb.com" data-send="false" data-layout="button_count" data-width="240" data-show-faces="false"></div> <div class="fb-comments" data-href="http://www.heretheweb.com" data-num-posts="5" data-width="470"></div> <body> </html> 

星期一的第一个实现是在4个平台,包括模拟器(iOS 4和iOS 5),iPhone 3G iOS4和iPhone 4 iOS 5中获得成功。星期二,我继续开发这个,最后我用自定义UIWebView工作,没有任何问题前三名。 但在iPhone 4(iOS 5)上,Web视图不断重新加载相同的网页,从而导致评论框从不出现。 该URL是这样的:

https://m.facebook.com/plugins/comments.php?channel_url=http%3A%2F%2Fstatic.ak.facebook.com%2Fconnect%2Fxd_arbiter.php%3Fversion%3D4%23cb%3Df28c738848%26origin%3Dhttp% 253A%252F%252Fwww.heretheweb.com%252Ff3fdf142e8%26domain%3Dwww.heretheweb.com%26relation%3Dparent.parent&HREF = HTTP%3A%2F%2Fwww.heretheweb.com&语言环境= EN_US&移动=真numposts = 5&SDK =乔伊&宽度= 470

我不知道我在做什么错误,我已经清理了uiWebView的委托方法,我已经检查了断点所有我可以覆盖的方法。 没有…网页在开始时被加载,然后循环尝试加载上面的URL …

在评论插件被加载到启用Retina的设备上时,Facebook评论插件中存在一个错误,导致无限的加载循环。

在fb js脚本中有一行代码如下:

if(window.devicePixelRatio>1)document.location.reload()

所以如果你正在访问高密度屏幕设备上的页面,你注定要失败。

我在这里报告了这个问题

我想出了一个肮脏的黑客修复它,但使用它之前三思,它可能会停止工作在任何时候。

请注意,这种方法只适用于在UIWebView中embedded插件,如果您在Safari中访问页面时遇到问题,没有其他select,只能等待来自Facebook的修复。

我的想法是当它被UIWebView加载时,“修复”js代码。

为了处理请求,我创build了自己的NSURLProtocol实现:

 <FBCommentsFixingURLProtocol.h> #import <Foundation/Foundation.h> @interface FBCommentsFixingURLProtocol : NSURLProtocol @end <FBCommentsFixingURLProtocol.m> #import "FBCommentsFixingURLProtocol.h" static NSString *FBCommentsFixingHeader = @"X-FBFix"; @interface FBCommentsFixingURLProtocol () @property (nonatomic, readwrite, strong) NSURLRequest *request; @property (nonatomic, readwrite, strong) NSURLConnection *connection; @property (nonatomic, readwrite, strong) NSURLResponse *response; @end @implementation FBCommentsFixingURLProtocol @synthesize request = request_; @synthesize connection = connection_; @synthesize response = response_; + (BOOL)canInitWithRequest:(NSURLRequest *)request { if (([request.URL.scheme isEqualToString:@"https"] || [request.URL.scheme isEqualToString:@"http"]) && [request.URL.absoluteString rangeOfString:@"facebook.com/plugins/comments.php"].location != NSNotFound && [request valueForHTTPHeaderField:FBCommentsFixingHeader] == nil) { return YES; } return NO; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } - (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id <NSURLProtocolClient>)client { // Modify request so we don't loop NSMutableURLRequest *myRequest = [request mutableCopy]; [myRequest setValue:@"" forHTTPHeaderField:FBCommentsFixingHeader]; self = [super initWithRequest:myRequest cachedResponse:cachedResponse client:client]; if (self) { [self setRequest:myRequest]; } return self; } - (void)startLoading { NSURLConnection *connection = [NSURLConnection connectionWithRequest:[self request] delegate:self]; [self setConnection:connection]; } - (void)stopLoading { [[self connection] cancel]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSString *dataAsString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; //Just modify the script to prevent it from execution on Retina devices. //window.devicePixelRatio = 2 for the Retina Display NSString* modified = [dataAsString stringByReplacingOccurrencesOfString:@"if(window.devicePixelRatio>1)document.location.reload();" withString:@""]; NSData* dataMod=[modified dataUsingEncoding:NSUTF8StringEncoding]; [[self client] URLProtocol:self didLoadData:dataMod]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [[self client] URLProtocol:self didFailWithError:error]; [self setConnection:nil]; } - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [self setResponse:response]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [[self client] URLProtocolDidFinishLoading:self]; [self setConnection:nil]; } @end 

然后我在应用程序代理didFinishLaunchingWithOptions中注册它:

 [NSURLProtocol registerClass:[FBCommentsFixingURLProtocol class]]; 

我知道这是一个肮脏的黑客,但仍然有效。

好的…解决了。 对于一些奇怪的和怪异的原因,有时只在iPhone 4(不是模拟器,iPhone 3G或iPad 2)中加载注释Web部件时,它会尝试重新加载一次(Cache-Control头部设置为max-age = 0 ,所以它一直强迫重载)

解决scheme是检查UIWebViewNavigationType,如果它等于UIWebViewNavigationTypeReload,则shouldStartLoadWithRequest:返回NO。

这是非常棘手的¬¬

我在safari / ios mobile下有一个相同的问题,在sencha touch 1上开发的一个web应用程序,它在其他浏览器下工作,所以在它上面,它不断的加载和加载。 我找不到线索。

下面的代码对我来说工作得很好

 UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)]; NSString *html = @"<div id=\"fb-root\"></div><script>(function(d, s, id) {var js, fjs = d.getElementsByTagName(s)[0];if (d.getElementById(id)) return;js = d.createElement(s); js.id = id;js.src = \"https://connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v2.5\";fjs.parentNode.insertBefore(js, fjs);}(document, 'script', 'facebook-jssdk'));</script><div class=\"fb-comments\" data-href=\"URL_OF_YOUR_PAGE\" data-numposts=\"5\"></div>"; [webView loadHTMLString:html baseURL:[NSURL URLWithString:@"https://facebook.com"]]; [self.view addSubview:webView];