部分原因是为了学习一点iOS编程,部分是因为我希望我在iPad上有一个WhatsApp客户端,我正在尝试创建一个我个人可以用作iPad的WhatsApp客户端的应用程序。它所做的就是在UIWebView中加载web.whatsapp.com桌面站点,如下所示:
override func viewDidLoad() {
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"])
super.viewDidLoad()
self.webView.frame = self.view.bounds
self.webView.scalesPageToFit = true
// Do any additional setup after loading the view, typically from a nib.
let url = NSURL(string: "https://web.whatsapp.com")
let requestObj = NSMutableURLRequest(URL: url!)
webView.loadRequest(requestObj)
//webView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
}
这没关系。事实上它确实加载了正确的webapp,而不是像服务器检测到移动设备时那样重定向到whatsapp主页。但是,我没有向我提供登录的QR码屏幕,而是向我展示了这一点:
现在,如果我在iPad上使用Safari中的WhatsApp Web(并请求桌面版),它的效果非常好。如您所见,我通过设置UserAgent为我的UIWebView请求桌面站点。现在,我想知道为什么它在UIWebView中不起作用,是否可能需要设置其他标题或值以说服App在我的UIWebView控件中工作?
修改
通过将Boris Verebsky的代码从Objective-C转换为Swift,我已经改为WKWebView。然而,虽然起初我看到的屏幕与以前一样(告诉我使用另一个浏览器),在更改它并试图让它工作后,我发现自己有一个空白的白色屏幕。什么都没有出现了。
这是我目前的完整代码:
import UIKit
import WebKit
class ViewController: UIViewController, WKNavigationDelegate {
@IBOutlet var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView = WKWebView(frame: self.view.bounds)
if #available(iOS 9.0, *) {
self.webView.customUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"
} else {
// Fallback on earlier versions
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/601.5.17 (KHTML, like Gecko) Version/9.1 Safari/601.5.17"])
}
self.view!.addSubview(self.webView)
self.webView.navigationDelegate = self
// Do any additional setup after loading the view, typically from a nib.
let url: NSURL = NSURL(string: "http://web.whatsapp.com")!
let urlRequest: NSURLRequest = NSURLRequest(URL: url)
webView.loadRequest(urlRequest)
}
func webView(webView: WKWebView, decidePolicyForNavigationAction: WKNavigationAction, decisionHandler: WKNavigationActionPolicy -> Void) {
decisionHandler(.Allow)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
可能是我从Objective-C到Swift的转换不正确。我不熟悉Objective-C,所以很有可能。
答案 0 :(得分:9)
检查用户代理后,https://web.whatsapp.com检查客户端是否支持indexeddb,可能是某些JavaScript。它很容易注意到 - 如果您将跟踪您的应用执行的所有重定向,那么您会发现重定向到https://web.whatsapp.com/browsers.html?missing=indexeddb。在我的例子中,我使用简单的NSURLProtocol
子类来记录所有重定向。遗憾的是,NSURLProtocol
不再适用于WKWebView
。
UIWebView
根本没有实现indexeddb。据我所知,没有简单的方法可以自己实现indexeddb支持。
您可以通过访问UIWebView
中的html5test.com轻松检查indexeddb支持。你会看到类似的东西:
但WKWebView
支持indexeddb:
我已使用自定义用户代理检查了带有自定义用户代理的iOS WKWebView
中的web.whatsapp.com,并使用http://whatsmyuseragent.com从我的桌面Safari中获取,并显示了您预期的QR代码。此外,迁移到WKWebView
会增加一些奖励,例如改善性能和稳定性。
我已经使用以下代码进行测试:
#import <WebKit/WebKit.h>
@interface ViewController () <WKNavigationDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds];
self.webView.customUserAgent = @"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/601.6.17 (KHTML, like Gecko) Version/9.1.1 Safari/601.6.17";
[self.view addSubview:self.webView];
self.webView.navigationDelegate = self;
NSURL *url = [NSURL URLWithString:@"http://web.whatsapp.com"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:urlRequest];
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(nonnull WKNavigationAction *)navigationAction decisionHandler:(nonnull void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler(WKNavigationActionPolicyAllow);
}
@end
虽然它是Objective-C,但转换成swift应该非常简单。
<强> UPD:强>
WKWebView
空白视图的原因是传输安全性。使用https://web.whatsapp.com
作为URL(注意HTTPS而不是HTTP),或在应用程序info.plist中添加NSAllowsArbitraryLoads: YES
答案 1 :(得分:4)
您应该切换到使用WKWebView
,然后您只需使用customUserAgent
直接在网络视图上设置所需的代理字符串。