RainedAllNight‘s Blog

iOS中的URL

字数统计: 1.7k阅读时长: 6 min
2017/04/02 Share

1. 网络通信中的URL

我们使用这种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

如图,使我们经常会添加的几个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相关的知识会在下面补充

CATALOG
  1. 1. 1. 网络通信中的URL
    1. 1.0.1. URL的结构
    2. 1.0.2. URL的拆分
  • 2. 2. openURL
    1. 2.0.1. 应用间的跳转: