通过iOS 9 SFSafariViewController提供完整的Web浏览体验
http://www.cocoachina.com/ios/20150826/13157.html

本文由CocoaChina译者@涛声依旧-忆往昔翻译自tutsplus
校对:BenBeng
原文:iOS 9: Getting Started With SFSafariViewController?
当前,移动应用和各种网络上的内容已无所不在。多年以来, iOS开发者都是要么在APP中创建自己的web浏览体验,要么让Safari来打开URL。这两种方法都有不可避免的缺点。不过,现在这一切都改变了, iOS 9引入了SFSafariViewController类。你可以通过它在APP中提供完整的web浏览体验,无需浪费重要的开发时间。
1.Demo演示概要
开始前,先讲下本教程使用的demo应用中用到的几种方法。正如您稍后将看到的,使用Safari的view controller没有涉及太多的代码。Safari view controller的真正价值在于知道何时使用它,更重要的是为什么使用它。
显示Web内容的三种方法
在iOS 9中,开发者有三种方法来显示Web内容:
Safari:使用openURL(_:)在Safari中展示页面,会不得不让用户离开你的应用。
自定义浏览体验:你可以利用WKWebView或UIWebView从头开始创建浏览体验。
SFSafariViewController :通过SFSafariViewController,你几乎可以使用所有Safari的一些便利特性,而无需让用户离开你的应用。
iOS9之前,开发者只能使用前两种方法。了解何时使用其中一个或另一个取决于所呈现内容哪种方法。虽然本教程使用的是demo应用,但我们将使用全部三种方法。
现在我们知道了如何显示内容,那来概括下为什么会在应用中展示。在iOS上,查看web内容主要有两种情况。
自定义Web内容:这些内容不是用于浏览的。这可能是一个报告或是从API或服务器生成的类似的东西。这里,用户查看的是一块儿内容,而不是做别的。
浏览网站:这是最常见的场景。用户需要随时浏览网页来登录到服务或浏览网站。
也请记住还有第三种情况--基于Web的验证。在本教程中,我们不会把重点放在这个情景中。
自定义Web内容
如果用户在APP中的Web体验的属于第一个用例,那么view controller可能不是你需要的。在这种情况下,您将显示自己的控件和内容,并且可能需要大量的自定义。
如果你发现你的应用适合这种情况下,使用WKWebView 。它是UIWebView的继任者,并包括几个增强功能,如使用 Nitro Javascript engine。这种方法可以让你从头开始构建整个用户界面。还有其他的功能,如安全加载文件和使用WKWebsiteDataStore查询cookies。
浏览网站
其实,大多数的应用,只需要提供一个一般的网络浏览体验。这是使用safari view controller的完美场景。
在iOS9之前,开发者花时间创建自己的用户界面来浏览网页,用户在使用时也可能遇到一些问题。
在不同的应用之间,浏览网页的体验是不同的,这可能会让用户感到疑惑。某些界面可能缺少用户期望的东西,比如表示网页加载进度的进度条。
此外,你也不能使用Safari的全部功能。这包括阅读器视图,自动填充功能用到的iCloud钥匙串等等。如果你想在iOS 9 之前实现这些功能,就不得不让用户完全离开你的应用,去到Safari里打开这些网页。。而SFSafariViewController类解决了所有这些问题。
2.运行演示应用
首先,构建和运行演示应用。你将会看到,有三个选项一个很简单的用户界面。每个选项对应一个前面提到的展示web内容的方法。

3. 在Safari中打开网页
在第一个选项中,我们会展示一个比较传统的方法,就是让Safari来打开URL。打开ViewController.swift并注意在该文件的顶部urlString属性。它定义的是下面的例子要展示的内容,可以随意将其设置为任何你想要的。
|
1
|
|
需要注意的一件重要的事情是,在iOS中9 ,会默认使用TSL 1.2。如果您要访问的服务器不支持此功能,你会在控制台中看到以下错误:

这种情况有解决办法,比如在你的应用的Info.plist文件中添加一个key。Apple的这个改动是为了提高浏览网络时的安全。接下来,把
下面的代码添加到openInSafari ( _ :)方法中:
|
1
2
3
4
5
|
@IBAction func openInSafari(sender: AnyObject){ let url = NSURL(string: self.urlString)! UIApplication.sharedApplication().openURL(url)} |
构建并运行应用。当你点击顶部的"Open in Safari"按钮,操作系统会离开你的应用并在Safari浏览器中打开URL。

虽然这种方法是可行的,但是我们不得不让用户离开我们的应用。作为开发人员,理想情况下,我们想让用户一直呆在我们的应用里。iOS 9已经对此做了一些改进,就是在左上角有一个小的返回按钮。

点击此按钮将用户返回到用Safari打开URL的应用。为了解决用户不得不离开我们应用的问题,让我们进入下一个方法。
4. 在WebKit或WebView中打开网页
现在,我们将我们的应用内打开相同的URL 。要做到这一点,我们将嵌入一个UIWebView 。这个简单的网页浏览器的逻辑可以在CustomWebViewController类中找到。
因为我们不需要任何的WebKit的高级功能,我们只需在web view中打开。在ViewController类中,把prepareForSegue(_:sender:)替换成下面的代码:
|
1
2
3
4
5
6
7
8
|
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?){ if let navVC = segue.destinationViewController as? UINavigationController { let cwvc = navVC.topViewController as! CustomWebViewController cwvc.urlString = self.urlString }} |
运行应用。点击中间的"Open with webview"按钮,现在网页就会在应用里加载了?
即使用户还呆在我们的应用中,这种方法的缺点是显而易见的。如果我们这边不进行额外的开发,那么界面上就没有进度条、地址栏等用户在浏览网页时需要的东西。现在让我们使用SFSafariViewController类来解决这些问题。
5. 在Safari View Controller中打开网页
在我们使用SFSafariViewController之前,需要引入Safari Services。在ViewController.swift的顶部,在UIKit的import语句下面添加如下的代码:
|
1
|
import SafariServices |
下一步,更新openWithSafariVC ( _ :)的实现,如下所示:
|
1
2
3
4
5
|
@IBAction func openWithSafariVC(sender: AnyObject){ let svc = SFSafariViewController(URL: NSURL(string: self.urlString)!) self.presentViewController(svc, animated: true, completion: nil)} |
运行应用并点击底部的"Open with safari view controller"按钮,现在能看到网页是在SFSafariViewController实例中展示的。

现在,我们既让用户停留在我们的应用中,又让用户能利用Safari的全部优点。在tab bar中,用户可以呼出分享菜单,也能把网页添加到收藏,或者是在Safari中打开网页。
还有很多有意思的配置可以利用。比如,我们可以给entersReaderIfAvailable传入true,来让用户能轻松调出阅读器模式:
|
1
2
3
4
5
|
@IBAction func openWithSafariVC(sender: AnyObject){ let svc = SFSafariViewController(URL: NSURL(string: self.urlString)!, entersReaderIfAvailable: true) self.presentViewController(svc, animated: true, completion: nil)} |
此外, Safari view controller 也使用tint color。这能让你的应用在保持统一风格的同时,也保留熟悉的Safari的UI
然而,还有一个问题是目前用户无法关闭这个页面。现在让我们来解决这个问题。
6. SFSafariViewControllerDelegate协议
要关闭view controller,我们需要遵从SFSafariViewControllerDelegate协议。打开ViewController.swift并使ViewController类遵从SFSafariViewControllerDelegate协议。
|
1
2
3
4
|
class ViewController: UIViewController, SFSafariViewControllerDelegate{ ...} |
接着,将下面的委托方法添加到ViewController类:
|
1
2
3
4
|
func safariViewControllerDidFinish(controller: SFSafariViewController){ controller.dismissViewControllerAnimated(true, completion: nil)} |
当用户点击Safari view controller上的Done按钮时,会调用该委托方法。它应该被用来关闭该view controller,并返回到你的应用。
剩下要做的事就是把我们的view controller设为Safari view controller的delegate。更新openWithSafariVC ( _ :)方法的实现,如下所示:
|
1
2
3
4
5
6
|
@IBAction func openWithSafariVC(sender: AnyObject){ let svc = SFSafariViewController(URL: NSURL(string: self.urlString)!) svc.delegate = self self.presentViewController(svc, animated: true, completion: nil)} |
如果你运行应用并打开Safari view controller,你会看到,你现在可以通过点击右上角的Done按钮来关闭Safari view controller了。
结论
View controller是非常容易使用。事实上,这是我见过的最小的API之一了,它只有两个初始化方法和两个委托方法。即便如此,它将Safari中用户期望的全部功能带到了你的应用中。
同样令人兴奋的是,开发者将不再需要花时间创建自定义的Web浏览器。只需SFSafariViewController的几行代码,就能为你的应用带来一流的web浏览体验。
通过iOS 9 SFSafariViewController提供完整的Web浏览体验的更多相关文章
- Atitit 知识图谱解决方案:提供完整知识体系架构的搜索与知识结果overview
Atitit 知识图谱解决方案:提供完整知识体系架构的搜索与知识结果overview 知识图谱的表示和在搜索中的展1 提升Google搜索效果3 1.找到最想要的信息.3 2.提供最全面的摘要.4 ...
- 一个完整Java Web项目背后的密码
前言 最近自己做了几个Java Web项目,有公司的商业项目,也有个人做着玩的小项目,写篇文章记录总结一下收获,列举出在做项目的整个过程中,所需要用到的技能和知识点,带给还没有真正接触过完整Java ...
- UIView封装动画--iOS利用系统提供方法来做转场动画
UIView封装动画--iOS利用系统提供方法来做转场动画 UIViewAnimationOptions option; if (isNext) { option=UIViewAnimationOpt ...
- UIView封装动画--iOS利用系统提供方法来做关键帧动画
iOS利用系统提供方法来做关键帧动画 ios7以后才有用. /*关键帧动画 options:UIViewKeyframeAnimationOptions类型 */ [UIView animateKey ...
- UIView封装动画--iOS 利用系统提供方法来做弹性运动
iOS 利用系统提供方法来做弹性运动 /*创建弹性动画 damping:阻尼,范围0-1,阻尼越接近于0,弹性效果越明显 velocity:弹性复位的速度 */ [UIView animateWith ...
- ASP.NET MVC 提供与访问 Web Api
ASP.NET MVC 提供与访问 Web Api 一.提供一个 Web Api 新建一个项目,类型就选 "Web Api".我用的是MVC5,结果生成的项目一大堆东西,还编译不过 ...
- Web 浏览
Web 浏览为了更好地了解 CGI 的概念,让我们点击一个超链接,浏览一个特定的网页或 URL,看看会发生什么. 您的浏览器联系上 HTTP Web 服务器,并请求 URL,即文件名.Web 服务器将 ...
- 一个完整的 Web 请求到底发生了什么
阅读本文大概需要 7 分钟. 一.从输入一个网址开始 当我们在浏览器输入一个网址,然后按下回车,接下来浏览器显示了页面.网速好的话这之间可能就一秒,但在这一秒内到底发生了什么? 本文主要内容是试图记录 ...
- Web API设计方法论--比较完整的web api 开发过程
为Web设计.实现和维护API不仅仅是一项挑战:对很多公司来说,这是一项势在必行的任务.本系列将带领读者走过一段旅程,从为API确定业务用例到设计方法论,解决实现难题,并从长远的角度看待在Web上维护 ...
随机推荐
- mysql建表设置格式
建表时必须设置字段编码格式为COLLATE utf8_bin,表示查询时该字段内容区分大小写,如果不需要区分大小写,可以设置为COLLATE utf8_ genera_ci,表示忽略大小写
- LA3516 Exploring Pyramids
Exploring Pyramids 题目大意:给定一个欧拉序列(即每经过一个点,把这个点加入序列),问有多少种对应的多叉树 序列与树构造对应问题,考虑区间DP dp[i][j]表示序列i...j对应 ...
- ubuntu 环境下向GitHub上传(push)每次都需要用户名密码问题
这里使用的系统环境是ubuntu16.04,通过Git向GitHub仓库pull/push,使用https方式每次都需要输入用户名和密码,是解决此问题的方法. 一.应该确保你的系统上已经安装了Git ...
- 如何实现一个HTTP请求库——axios源码阅读与分析 JavaScript
概述 在前端开发过程中,我们经常会遇到需要发送异步请求的情况.而使用一个功能齐全,接口完善的HTTP请求库,能够在很大程度上减少我们的开发成本,提高我们的开发效率. axios是一个在近些年来非常火的 ...
- JAVA面试常见问题之常见集合篇
1.List 和 Set 区别 List 可以允许重复的对象. 可以插入多个null元素. 有序容器 Set 不允许重复的对象. 只能插入1个null元素 无序容器,可以使用TreeSet实现有序 2 ...
- 使用koa-body中间件后DELETE请求中ctx.request.body内容为空
gitbook浏览此随笔 出现场景 在使用koa-body 做文件上传的时候,发现使用DELETE请求时,request.body中的内容为空对象{} app.js //code... const K ...
- ios h5 出现的问题
这几天在测试的时候,忽然发现手机ios 页面中的input 样式出现问题,安卓就没事. 实际应该是第一张图,在ios中出现的结果为第二张图 出现这个原因,主要是ios系统自带的设置,解决方法为 ...
- UOJ#422. 【集训队作业2018】小Z的礼物
#422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...
- Java是如何实现跨平台的
一.Java是如何实现跨平台的 1.我们编写的Java源码,编译后会生成一种 .class 文件,称为字节码文件 2.Java虚拟机JVM就是负责将字节码文件翻译成特定平台下的机器码然后运行.也就是说 ...
- 微信小程序之threejs全景
最近在开发小程序,身心疲惫,原因是功能和app相同,我裂开了. 各种封装组件,各种写页面,不过有个好处是以前写的h5拿来改一下标签,基本上还是ok的,就剩下最后几个功能,其中就有一个VR全景功能. 移 ...