加载页面后,无法在UIWebview中更改UserAgent

时间:2015-03-29 00:54:13

标签: ios uiwebview

我的IOS应用程序中有几个UIWebView。有时,用户可能需要从任何给定URL的移动站点更改为桌面站点。我正在使用欺骗来改变UserAgent:

 + (void) startSpoofingUserAgent
 {
     [[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"UserAgent" : @"Desktop" }];
     [[NSUserDefaults standardUserDefaults] synchronize];
 }

我还有一种可以杀死欺骗的方法:

 + (void)stopSpoofingUserAgent
 {
      NSDictionary *registeredDefaults = [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSRegistrationDomain];
      if ([registeredDefaults objectForKey:@"UserAgent"] != nil)
      {
          NSMutableDictionary *mutableCopy = [NSMutableDictionary dictionaryWithDictionary:registeredDefaults];
          [mutableCopy removeObjectForKey:@"UserAgent"];
          [[NSUserDefaults standardUserDefaults] setVolatileDomain:mutableCopy forName:NSRegistrationDomain];
          [[NSUserDefaults standardUserDefaults] synchronize];
      }
}

然后,我让用户可以通过按钮从桌面到移动和移动到桌面进行更改。然后我用这段代码重新加载URL:

        self.webView.delegate = self;
        self.webView.scalesPageToFit = YES;
        self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

        //Create a URL object.
        NSURL *url = [NSURL URLWithString:self.convertedURL];

        //URL Request Object
        if(self.defaultToDesktopSite)
        {
            [MINNetworkingUtils startSpoofingUserAgent];
        }
        else
        {
            [MINNetworkingUtils stopSpoofingUserAgent];
        }

        NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];

        //Load the request in the UIWebView.
        [self.webView loadRequest:requestObj];

我还缓冲用户具有UIWebView的当前状态,以便它跨实例保留设置。应用程序第一次运行时,无论它处于哪种状态(桌面或移动),它都能正常运行。

问题: 问题是我无法改变状态,并在初始加载后在应用程序中反映出来。

情景1:

  • 用户运行应用
  • UIWebView设置为欺骗UserAgent,从而强制UIWebView加载桌面网站
  • 工作很棒!

情景2:

  • 用户运行应用
  • UIWebView设置为不欺骗UserAgent,从而让UIWebView加载移动网站(如果可用)
  • 工作很棒!

情景3:

  • 用户运行应用
  • UIWebView设置为欺骗UserAgent
  • 网站提供桌面网站(正如预期的那样)
  • 用户通过选择按钮
  • 将状态更改为“移动”
  • 应用程序使用上面的代码重新加载UIWebView(UN-spoofs连接)
  • 不工作
  • UIWebView重新加载,但它仍在使用“桌面”网站,而不是移动网站
  • (如果逆转,这个场景的工作方式相同。换句话说,如果UIWebView第一次出现在“移动”中。它会一直有效,直到我尝试更改它并重新加载它。)

情景4:

  • 执行与场景3相同的步骤但是从内存中卸载应用程序并重新加载应用程序
  • 由于我记录状态,当应用程序出现时,UIWebView认为它应该以“移动”模式出现(因为用户在上次运行应用程序时更改了它)。
  • 再次工作! UIWebView以“移动”模式启动。

似乎正在发生的事情是UIWebView在某处缓冲某些内容并且不允许我使用不同的欺骗重新加载UIWebView。如果卸载并重新加载应用程序,UIWebView将按预期工作。

我尝试过以下方法强制UIWebView不缓冲任何内容并且没有成功:

 [[NSURLCache sharedURLCache] removeAllCachedResponses];
 ... reload URL

  self.convertedPageURL = [NSString stringWithFormat:@"%@?t=%@", self.convertedPageURL, randomString];
  ... reload URL

就像我说的那样,我无法让UIWebView从桌面移动到移动或移动到桌面,无需卸载应用程序并重新加载。

HELP !!!

修改

这是我用来获取当前值的代码。一旦我调用了这行代码,我就再也无法更改UserAgent了:

         defaultUserAgentString = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"];

1 个答案:

答案 0 :(得分:5)

UserAgent user-defaults键是私有API。因此,它没有保证的行为。所有答案都是经验性的。

话虽如此,听起来正确的解决方案是在每次更改后杀死并重新创建UIWebViewUIView不符合NSCopying,因此您需要执行以下手动操作:

UIWebView *newWebView = [[UIWebView alloc] initWithFrame:self.webView.frame];
newWebView.delegate = self;
newWebView.scalesPageToFit = YES;
// ... and the autoreseizing mask, etc — no need to do this upon every load

[self.webView.superview insertSubview:newWebView aboveSubview:self.webView];
[self.webView removeFromSuperview];
self.webView = newWebView;

如果无效,您可能需要切换到设置用户代理的文档化方法。我建议您实施自己的NSURLProtocol处理程序,该处理程序接受尚未看到的httphttps个请求,修改标头字段并再次发送它们,该时间拒绝接受他们让他们下降到系统。这将是麻烦但它将允许您可靠地立即改变它或任何其他标题字段。

有关示例,请参阅kifi's engineering blog