6

最近我一直在尝试将 Facebook 社交插件集成到 iOS 中的自定义 UIWebView 中,用于评论网页。我添加了 Like 按钮和 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) 上,网络视图不断地重新加载同一个网页,导致评论框永远不会出现。该网址是这样的:

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&locale=en_US&mobile=true&numposts=5&sdk=joey&width=470

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

4

4 回答 4

5

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

在一个 fb js 脚本中有一行如下所示:

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

因此,如果您在具有高密度屏幕的设备上访问该页面,那么您注定要失败。

我在这里报告了这个问题

我想出了一个肮脏的黑客来修复它,但在使用它之前要三思而后行,它可能随时停止工作。

请注意,此方法仅在您将插件嵌入 UIWebView 时有效,如果您在访问 safari 中的页面时遇到问题,则别无选择,只能等待来自 facebook 的修复。

我的想法是在 UIWebView 加载 js 代码时即时“修复”它。

为了即时处理请求,我创建了自己的 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]];

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

于 2012-08-01T13:07:30.250 回答
1

好的...解决了。由于某些奇怪和奇怪的原因,有时仅在 iPhone 4(不是模拟器、iPhone 3G 或 iPad 2)中加载评论 Web 部件时,它会尝试一次又一次地重新加载(Cache-Control 标头设置为 max-age=0 ,所以它一直强制重新加载)

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

这真的很棘手 ¬¬

于 2012-04-19T13:06:26.387 回答
0

我在 safari/ios mobile 下也有同样的问题,在 sencha touch 1 上开发的 web 应用程序上,它可以在其他浏览器和 SO 下工作,但是在这个问题上,它一直在加载和加载。我找不到线索。

于 2012-07-13T17:38:07.113 回答
0

下面的代码对我来说工作正常

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];
于 2016-01-12T13:19:52.717 回答