SafariServices

SFSafariViewController

App可以选择UIWebView和WKWebView,展现Web内容。但是某些情况下,App既想使用类似于Safari的浏览器框架来打开网页,又不想自己重写地址栏工具栏,那么SFSafariViewController就是一个最好的选择,效果如图:

SFSafariViewController是一个特殊的UIViewController,可在当前App使用Safari的UI框架展现Web内容,同时还能享受到Safari的一些便利特性,包括但不限于:

  • 相似的用户体验
  • 和Safari共享Cookie
  • 密码、证书自动填充
  • Safari阅读器

缺点也是很明显的:SFSafariViewController的可定制性极差,甚至连地址栏都是不可编辑的,只能在init的时候,传入一个URL来指定网页的地址。另外一个定制功能在于SFSafariViewControllerDelegate里面的一个方法:

1
- (NSArray <UIActivity *> *)safariViewController:(SFSafariViewController *)controller activityItemsForURL:(NSURL *)URL title:(nullable NSString *)title;

可以传入UIActivity的数组,为UIActivityViewController(点击底部工具栏中间的按钮触发)添加各类插件式的服务。

题外话:

苹果为了巩固MobileSafari在iOS中Web的地位可谓是不遗余力:只允许使用iOS WebKit框架和WebKit Javascript浏览web内容,却只开放一个极低效率、极不灵活的UIWebView,以及一个开放度较高但bug成吨的WKWebView。不过一直以来,苹果还是以「限制」为主;从iOS 9开始,苹果开始重视App - 用户 - Web这条关系链,并为此开放了大量的新接口给开发者使用,SFSafariViewController就是其中之一。

App - 用户 - Web这条关系链中,最重要的是什么?用户数据。苹果通过SFSafariViewController,让App得以使用到用户最私密的Cookie和iCloud Web表单数据,App和Web的关系通过用户数据被拉近了,而Web的官方承载体依然是Safari —— 这是苹果想要强调的。

用户会关心什么呢?用户才不理那些深层次的玩意呢。完善的功能,便捷的体验才是用户关心的。SFSafariViewController就是一个内置于App的小型Safari,强行提高了Safari的曝光度,甚至可以借此俘获敌营用户。另一方面,SFSafariViewController去掉App跳转Safari的沉重感,减少App和Safari的割裂。

总的来说,这是一个多赢的结局。受损的可能只有第三方的浏览器——让第三方浏览器帮忙带Safari的量,开玩笑呢;另外假设一些由SFSafariViewController接触到Safari的用户,可能会从第三方浏览器阵营,转投Safari的怀抱。Safari的体验真不是吹的,特别是当你手上几乎都是苹果设备的时候。反正我早已从Chrome转投Safari,不用烧纸。

SFContentBlockerManager

目前的api文档中只有一个接口:

1
+ (void)reloadContentBlockerWithIdentifier:(NSString *)identifier completionHandler:(void (^__nullable)(NSError *__nullable error))completionHandler;

Content Blocker,据说是一个Browser Extension之类的玩意,和广告过滤的作用类似,目前功能不明,更多信息可以看这里

WebKit

目前WKWebView在iOS 9有点问题,无法用来测试新的API,只能通过API名称来猜测其用途。

WKWebView

1
@property (nullable, nonatomic, copy) NSString *customUserAgent NS_AVAILABLE(10_11, 9_0);

自定义WKWebView的UA。

1
2
- (nullable WKNavigation *)loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL NS_AVAILABLE(10_11, 9_0);
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);

loadData和loadFileURL,这两个网页加载数据的接口终于回来了T^T。

WKWebsiteDataRecord, WKWebsiteDataStore

可以操作WKWebView的数据记录

和UIWebView只能操作Cookies和URLCache不同,从API提供的数据类型可以看出,可以操作的记录包括了:

  • Disk Cache
  • Memory Cache
  • WebApp Cache
  • Cookies
  • Session Storage
  • Local Storage
  • WebSQL
  • Indexed DB

覆盖了所有网页的数据记录,解决了iOS 8上WKWebView操作NSHTTPCookie和NSURLCache无效的bug,同时比UIWebView更加先进:要知道UIWebView无法清除Local Storage有多令人恼火。

由于目前还没能实测WKWebView,尚不知道iOS 9上是否解决了WKWebView的其他bug,如WKWebView的请求不经过NSURLProtocol之类的问题。这些致命bug不解决的话,WKWebView很难实装到第三方浏览器中,具体更详细的原因可以看这里