1. 网络通信中的URL
我们使用这种url来向服务器请求或传递数据,俗称 “网络资源定位符”
URL的结构
protocol/scheme: 传输协议,比如http、https等
credentials(可选):一些http服务器支持通过url来校验用户信息,当然这是一种不普遍也不安全的方式
hostName:资源服务器的主机地址
port(可选):端口号,指定客户端应该连接哪个端口,如果忽略则使用默认端口。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项
path:绝对路径,由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。
query(可选):查询,url最后部分是查询字符串。这个值是从path用?隔开的。多个参数每个参数用&分隔。查询字符串不能包含回车空格换行字符
- fragment:信息片断,字符串,用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释
URL的拆分
我们已经知道一个URL的基本结构,那么在iOS中我们如何获取对应结构的元素呢,答案是利用系统的URLComponents 类进行处理
我们简单看下这个类的内部结构
几个初始化方法
public init?(url: URL, resolvingAgainstBaseURL resolve: Bool) public init?(url: URL, resolvingAgainstBaseURL resolve: Bool)....
- 属性
public var scheme: String? public var user: String? public var password: String? public var host: String? public var port: Int? public var path: String public var query: String? public var fragment: String? public var queryItems: [URLQueryItem]?
我们可以看到URL的每个结构在URLComponents中都有对应的属性
####举个栗子:
guard let urlComponents = URLComponents.init(string: “http://mobile.hktsc.cc/services/list?appPage=serviceList&brandId=1") else {
return
}
if let scheme = urlComponents.scheme {
print("scheme: \(scheme)")
}
if let user = urlComponents.user {
print("user: \(user)")
}
if let password = urlComponents.password {
print("password: \(password)")
}
if let host = urlComponents.host {
print("host: \(host)")
}
if let port = urlComponents.port {
print("port: \(port)")
}
print("path: \(urlComponents.path)")
if let query = urlComponents.query {
print("query: \(query)")
}
if let queryItems = urlComponents.queryItems {
print("queryItems: \(queryItems)")
for (index, queryItem) in queryItems.enumerated() {
print("第\(index)个queryItem name:\(queryItem.name)")
if let value = queryItem.value {
print("第\(index)个queryItem value:\(value)")
}
}
}
输出结果
scheme: http
host: mobile.hktsc.cc
path: /services/list
query: appPage=serviceList&brandId=1
queryItems: [appPage=serviceList, brandId=1]
第0个queryItem name:appPage
第0个queryItem value:serviceList
第1个queryItem name:brandId
第1个queryItem value:1
使用场景
常用的使用场景是URL参数的截取,或者根据url的不同进行一些不同的操作,比如跳转等等
2. openURL
openURL主要有下面几个主要的应用
应用间的跳转:
在iOS中我们可以通过URL Schemes + openURL方法实现应用间的跳转,下面先讲几个概念和方法
- URL Schemes:我们在工程中配置的 URL Schemes可以理解为我们App在手机上的一个地址(类比网络中的URL,比如http://www.baidu.com,他的schemes是http),其他的已安装的应用可以通过这个地址找到我们的App,实现跳转。当然这个URL Schemes可以有多个
如图,使我们经常会添加的几个URL Schemes,目的是为了第三方应用能够跳转回我们的App。
在iOS9之后,新增了 URL Schemes白名单的概念,这个稍后具体再讲
- openURL: 我们可以通过这个方法打开一个URL,假如我们这个URL的schemes和我们已安装的某个app的URL Schemes一样的话,我们就可以打开这个app。
比如你可以使用下面的方法直接跳转到微信
UIApplication.shared.openURL(URL(string: "weixin://")!)// iOS10之前
UIApplication.shared.open(URL(string: "weixin://")!, options: [:], completionHandler: nil) // iOS10
再或者我们常用的拨打电话
UIApplication.shared.openURL(URL(string: "tel://10086")!)
一般,我们在跳转之前都需要判断下能不能够打开这个url(能够打开则跳转,不能则提示或者隐藏什么的),系统为我们提供了canOpenURL这个方法来判断我们是否能够打开某个url.但是在iOS9之后,我们需要在info.plist中配置URL Schemes 白名单,只有添加了白名单,我们的这个方法才能生效。否则会提示“This app is not allowed to query for scheme”,如下图
想了解更多App的URL Schemes可以参考这个你所知道好玩有趣的 iOS URL Scheme 有哪些?
值得一提的是在iOS9之后当我们跳转进入其他App时,系统会在左上角默认提供一个反馈按钮
其实,我们在跳转时还能进行简单的App间传参
如何传参:
类比于网络中的url,我们open的url其实也是这种结构,url中的scheme决定了我们要跳转的位置,其他的结构则可以用来传递我们的参数。
举个栗子:
我们使用第三方地图软件来进行导航时,在跳转时就需要将我们的目标位置参数传递过去
来看下官方提供的url格式
iosamap://navi?sourceApplication=applicationName&backScheme=applicationScheme&poiname=fangheng&poiid=BGVIS&lat=36.547901&lon=104.258354&dev=1&style=2
- iosamap:高德地图的官方url scheme,确保能跳到高德地图
- navi: url中的host,这边表示服务类型为导航
- sourceApplication,backScheme及后面的:这部分为url中query,我们需要传递的具体的参数
通过这个url我们可以直接从我们App跳到高德地图导航页面进行导航,当然前提是我们已经安装了高德地图,可以使用canOpenUrl来判断,具体的可参考高德官方的文档
那么高德内部是如何接收我们的参数的呢?,来看这两个熟悉的回调方法
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool
以上两个方法是系统提供给我们的openUrl回调方法,比如我们跳转到高德地图后,他那边就会执行这个方法,有一点需要注意的是第二个方法是在iOS9才出现的方法,也就是说如果你的系统是iOS9及之后的话他只会走第二个方法,iOS9之前才会走第一个方法。我们可以在这里获取相应的url并进行处理。我们平时会在这边处理友盟分享和支付相关的一些回调
##3. 本地文件的访问
url也可以用来访问我们本地的资源文件,其实和网络中的url一样,只不过资源服务器变成了我们本机,少去了资源传递的过程,最直接的资源定位符,这一块就先不做详细叙述了
##以上
###后续有URL相关的知识会在下面补充