我正在使用的iPhone应用程序使用WKWebView,但(我的客户端需要……)它必须有一个自定义用户代理.
我们希望用户代理字符串模仿Safari,它看起来像这样:
Mozilla / 5.0(iPhone; CPU iPhone OS 9_0_2,如Mac OS X)AppleWebKit / 601.1.46(KHTML,类似Gecko)版本/ 9.0 Mobile / 13A452 Safari / 601.1
我知道如何设置用户代理字符串.最简单的方法是将UserAgent设置为标准用户默认值.
[[NSUserDefaults standardUserDefaults] registerDefaults:@ {@“UserAgent”:userAgent}];
我遇到的问题实际上是提出Apple在Safari的User-Agent中使用的版本号.具体来说,AppleWebKit版本,即紧随Mobile(13A452)之后的代码,以及Safari版本号.
我提出的唯一解决方案涉及到
>实例化WKWebView
>从字符串加载虚拟页面(否则步骤3失败)
>在didFinishNavigation委托调用中,评估javascript以返回当前用户代理
>拉开UA以提取那些版本号
>构建一个类似于Safari的新字符串,但最后使用应用程序自己的名称/版本,并将Safari版本放入带有“like”的parens中,以产生以下结果:
Mozilla / 5.0(iPhone; CPU iPhone OS 9_0_1,如Mac OS X)AppleWebKit / 601.1.46(KHTML,如Gecko)版本/ 9.0 Mobile / 13A452(如Safari / 601.1)TheAppName / 1.12
(这两个iPhone版本是通过提供的系统调用找到的,这不是问题.)
有没有更好的办法? (显然,步骤3-4可以替换为通过javascript提取版本号,但这只会改变一切.)
简而言之,有没有什么方法可以获得AppleWebKit / Mobile / Safari版本号,而不是通过向webview实例询问其自己的用户代理字符串?
如果你不能按照上面的步骤,我可以提供一些示例代码甚至示例项目,但我的意图应该是明确的.
最佳答案 我认为你最好的选择是坚持你正在做的事情:这是派生一个非常类似于系统默认字符串的用户代理字符串的最安全的方法.即使创建Web视图,加载字符串以及查询用户代理存在开销,但在大型方案中它仍然是微不足道的.
另一方面,您感兴趣的数据应该从系统自己的框架中立即“废弃”.请记住,尽管iOS进程是沙盒,但这主要是为了防止它们访问其他应用程序的数据. iOS和Mac上的沙盒设计使应用程序进程能够从系统文件中大量读取,这是有道理的,因为这些文件支持代表应用程序将动态库和资源数据预期加载到内存中.
因此,例如在applicationDidFinishLaunching方法中添加这样的一行:
NSLog(@"System frameworks: %@", [[NSFileManager defaultManager] directoryContentsAtPath:@"/System/Library/Frameworks/" excludingDirectories:NO]);
您将看到所有可用系统框架的长列表.要正确使用WebKit框架的CFBundleVersion,例如:
NSLog(@"%@", [[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/Frameworks/WebKit.framework/Info.plist"] objectForKey:@"CFBundleVersion"]);
但是当然NSBundle将这个文件抽象出来,并让你直接得到可能已经在内存中的字典:
NSLog(@"%@", [[[NSBundle bundleForClass:[[WKWebView class] infoDictionary] objectForKey:@"CFBundleVersion"]);
您可以使用类似的技巧通过NSBundle的infoDictionaruy访问属性,或者直接从客户手机上的“磁盘”读取数据.