在 Swift 应用里构造和修改 NSURL

做者:Nick Hanan,原文连接,原文日期:2016-03-17
译者:BigbigChai;校对:walkingway;定稿:CMBhtml

许多应用程序都有访问文件的需求。也许是应用 bundle 或文件系统的文件,又或许是网上的资源。在代码里须要调用某些方法来指向这些文件。对于 Apple 平台而言,基本上只有两个选择:使用 String 或 NSURL。ios

使用过地址栏或任何终端的话,Swift 字符串将是一个很是容易理解的选择。个人意思是,全部的文本都是在地址栏的,对吧?Cocoa 和 Cocoa Touch SDK 中一些较旧的 API 都接收 NSURL 和字符串(一般在这些 API 中称为“路径”)做为参数,可是都愈来愈朝着只使用 NSURL 的方向发展。和 String 路径相比,NSURL 有许多优势,最明显的是能够访问 URL 各个部分的属性,而没必要另外编写代码来从路径的字符串解析出这些组件。git

请继续关注如何在 Swift 应用程序中学习建立和使用 NSURL。github

在 Swift 中建立 NSURL

在 Swift 中,有几个构造器和工厂方法能够用于建立 NSURL,可是我只打算说明其中比较有用的一部分。swift

init?(string URLString: String)

这是最普通,也许也是最经常使用的方法。这须要 Swift 字符串版本的 URL,并将其转换为 NSURL 对象。 这个构造器容许失败,由于不是全部字符串都能生成合法的 URL。有一些字符没法在 URL 中使用,所以须要使用 % 编码,它的出现表示了能够在 URL 中发送的编码。我我的最多见的是 %20,”空格“字符。这个构造器只接收有效的字符,它不会另外作 % 编码。所以,若是任何没法转换为合法 URL 的内容或字符串出现时,该构造器将返回 nil。app

let NSHipster = NSURL(string: "http://nshipster.com/")                  //returns a valid URL
    let invalidURL = NSURL(string: "www.example.com/This is a sentence");   //Returns nil

这其实是如下构造器的便利构造器。函数

init?(string URLString: String, relativeToURL baseURL: NSURL?)

这是容许定制的构造器。相似上一个构造器,它也是可失败的,接收相似的 URL Swift 字符串,同时也接受一个可选的 baseURL 对象(自己也是 NSURL)。若是 baseURL 为空,则彻底使用 URLString 建立 URL,这也许就是第一个构造器的内在实现。post

let NSHipsterTwo = NSURL(string: "http://nshipster.com/", relativeToURL: nil)   //Returns valid NSHipster URL
let article = NSURL(string: "ios9/", relativeToURL: NSHipster)

init(fileURLWithPath path: String, isDirectory isDir: Bool)

这相似于上面的构造器,只是用于指向本地文件或目录。我不肯定为何本地文件须要一个特殊版本,但我猜想它进行了一些优化(至少是以文件 scheme 开头,而不是 http 之类)。有另外一个版本没有 isDirectory 参数,但已知路径是否目录的话,头文件建议使用这个方法。也许由于另外一个版本将须要再执行检查,而这一个方法让用户提供了答案,能省下检查的步骤。学习

public init(fileURLWithPath path: String, isDirectory isDir: Bool, relativeToURL baseURL: NSURL?)

这是 iOS 9 中新增的方法。与上个方法相似,只是还加了 relativeToURL 参数。相似以前的构造器,这将返回一个NSURL,并将路径附加到 baseURL 后。若是有一个目录内的几个文件,有需求对这些文件进行迭代的时候,就能够利用这个方法了。能够提供文件所在的目录做为 baseURL,而后只需使用文件名做为 Swift 字符串路径建立 URL。优化

将 URL 转换回 Swift 字符串

有时候,特别是在处理较旧的 API 或要向用户展现时,须要将 NSURL 转换回 Swift 字符串。好在 NSURL 提供了一个简单的只读属性 absoluteString 来获取字符串。 NSURL 对象只需调用该属性就能得到:

let articleString = article?.absoluteString
//ArticleString now contains: "http://nshipster.com/ios9/"

在这种状况,接收了以前使用 relativeToURL 版本的构造器定义的 article 常量,从 scheme 直到结尾(在这种状况下是一个路径)把它解析成一个完整的 URL。若是一个 URL 包含文件扩展名(file extension),查询(query)和片断(fragment),也会把它们解析出来。可失败的构造器返回了原来的 article 对象,所以仍然有那个表示 Swift 可选链的问号。

修改 NSURL

这些函数都是基于被调用的 NSURL 返回一个新的、根据需求修改过的 NSURL。他们改变被调用的NSURL。

func URLByAppendingPathComponent(pathComponent: String, isDirectory: Bool) -> NSURL

这个方法给 URL 添加更多的路径组件,例如说你要添加一个文件到当前目录(存储在调用的 NSURL)。跟其余一些构造器同样,它有另外一个没有 isDirectory 参数的版本。但若是能明确它是否为目录的话,建议使用这一个。由于这能省去用来肯定是否目录的元数据检查。

var URLByDeletingLastPathComponent: NSURL? {get}

此属性将返回一个新的、删除了最后一个路径组件的 NSURL。这只修改 URL 的路径组件,URL 的其余组件(例如域名)不受影响。咱们能够这样写:

//articleTwo now contains "http://nshipster.com/ios9/"
 
let deletePathComp = articleTwo?.URLByDeletingLastPathComponent
//deletePathComp now contains "http://nshipster.com/"

没有路径信息的话,结果可能会变得有点诡异。为了好玩,我链式调用了几个URLByDeletingLastPathComponent,但最后只是在后面附加了“../”,相似命令行(cd ..)返回上一个目录。

还有几个修改方法和属性,但这些多是最经常使用的了。

Conclusion

All code in this post was tested in Xcode 7.3.1.

若是你好奇 URL 格式规范的细节,能够查看 Apple 的 NSURL 类型参考在处理 URL 部分提到的 RFC 文档。初始化 URL 时使用的字符串必须符合 RFC 2396,而且 URL 自己根据 RFC 1738RFC 1808 进行解析。这些规范内容不少,但你能找到全部可能关于 URL,URI 等的信息。

NSURL 中还有不少其余的属性。若是你想要一个彻底解析的 NSURL,baseURL,主机(host),查询(query),片断(fragment)等,你能够查看 Apple 的 NSURL 类型参考。但对我我的而言,主要使用了 absoluteString,偶尔也会用到 pathExtension。

但愿这篇文章对你有帮助。若是有,请在 Twitter 或任何社交媒体上分享这个帖子,每次分享都有裨益。固然,若是有任何问题,也请在联系页面 或 Twitter @CodingExplorer 上联系我,我会尽可能解答的。谢谢!

参考来源

本文由 SwiftGG 翻译组翻译,已经得到做者翻译受权,最新文章请访问 http://swift.gg