苹果的每一次升级,都让广大的iOS开发者又爱又恨:一方面,新的API的引入让程序员可以更好的发挥硬件的潜力为用户带来新功能;另一方面,iOS的向后兼容从来不是一件省心的事,以前工作得好好的功能可能就停摆了,或者以前正常的显示,可能在新版本里就错乱了。
这次iOS11的到来也是一样的,我们为新的功能惊喜,也为潜在的问题而忧虑。比如新的模拟器看起来高大上,可以居然不在可以随便设置分辨率。在macbook上都没法为 iPad Pro 12.9' 截屏了!
最近有用户反应MarkNote笔记目录( [TOC])不能跳转。研究了一下发现是<a name=name-of-link
>定义的锚点失效了。进一步的研究发现:
- 不光我的应用存在这个问题,其他凡是在 UIWebView 中加载本地HTML文件或者字符串的应用也一样都存在这个问题;
- 如果页面是 HTTP/HTTPS协议的则没有问题;
- 如果页面是
file:///
协议的则使用<a name=name-of-link
>定义的锚点失效; - 同样的功能在 iOS 10.3上运行正常;
在UIWebView的事件中设端点发现,点击锚点时还是触发了shouldStartLoadWithRequest
事件,但是 didFailLoadWithError 中没有任何错误。看起来的感觉是, UIWebView 看到是 file:///
协议的就不理睬锚点的跳转了。
既然如此,看来需要在 shouldStartLoadWithRequest
事件中做文章,注入一段javascript,让锚点滚动到可见区域来。简单的弄了一个方案:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
if (UIWebViewNavigationTypeLinkClicked == navigationType
&& [@"file" isEqualToString:[[request URL] scheme] ]) {
NSArray<NSString*>* components = [request.URL.absoluteString componentsSeparatedByString:@"#"];
if (components.count == 2) {
NSString* anchor = components.lastObject;
NSString* code = [NSString stringWithFormat:@"let element = document.getElementsByName(\"%@\")[0]; if (element) {element.scrollIntoView();}", anchor];
[webView stringByEvaluatingJavaScriptFromString:code];
return NO;
}
}
// 其他逻辑
}
测试通过。准备再测试一下,然后默默的发一个补丁了。