NSURL 的这些特性你注意到过吗

swift 发布于 2017年11月20日
NSURL 可以操作本地文件

我们通常理解的 URL,是指向一个服务端资源的。 但 NSURL 还可以指向本地文件:

if let documentRoot = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {

    var fileURL = NSURL(fileURLWithPath: documentRoot)
    fileURL = fileURL.URLByAppendingPathComponent("test.txt")

}

通过这个 URL 我们同样可以访问到本地的文件系统。 这种类型的 URL 称为 Path-based URL。

App 的沙盒文件目录可以以 NSURL 的形式返回:

前面那个例子中用 NSSearchPathForDirectoriesInDomains 方法获得了 Document 文件夹的路径, 是一个字符串形式的路径。 除了这种方式,NSFileManager 还给我们提供了一种获取这个目录对应的 URL 的方法:

if let documentURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first {

    print (documentURL)

}

documentURL 是一个 NSURL 实例,我们使用它同样可以进行文件系统的操作。 而且苹果推荐我们使用 URL 的形式来进行文件相关的操作。 至于为什么推荐使用 NSURL, 我们继续道来。

文件引用 URL

NSURL 除了我们刚开始展示的 Path-based URL 类型之外。 还提供了一个叫做 File reference URL 的类型。 我们只需要对我们刚刚创建的 fileURL 对象调用:

fileURL.fileReferenceURL()

这样既可得到相对于这个 URL 的 File reference URL 了。 那么所谓的 File reference URL 有什么用呢? 举个例子, 如果我们使用普通的 URL 对象,如果在我们操作这个 URL 之前, 另外一个操作把它对应的文件移动或者删除了。 那么我们的访问就会失败。 因为我们原来所指向的资源不存在了。

如果使用 File reference URL 的话,它指向的是这个资源本身,而不是它的路径。所以即便这个文件被移动了,我们依然能通过这个 URL 访问到它。 这也是 NSURL 对象相对于纯字符串文件路径的一个附加能力了。

Bookmark

NSURL 还提供了一个更加强大的能力,叫做 Bookmark。 Bookmark 又是什么鬼呢。 咱们再来看一个问题, 前面提到了 File reference URL,在原始文件被移动的时候也可以继续引用到这个文件。 但 iOS App 还有一个特点,File reference URL 的引用 ID 在 App 重新启动后会被改变。 也就是说 File reference URL 可以解决文件被修改的引用问题,但依然不能处理应用重新启动后的文件引用问题。

这就是 Bookmark 的由来了。 Bookmark 提供了一个更强的引用,无论文件被移动,还是应用重新启动,它都可以正确的引用。当然类似这样的能力也许不是所有的 App 都需要, 但如果你正好需要这个能力,而又了解到 iOS 其实已经给我们提供了,就不需要费力气自己去实现了。

创建 Bookmark 我们依然要通过 NSURL 对象:

do {

    let bookmark = try fileURL.bookmarkDataWithOptions(.SuitableForBookmarkFile, includingResourceValuesForKeys: nil, relativeToURL: nil)

} catch {

}

bookmark 其实就是一个 NSData 对象,里面存储着引用我们这个文件所需的相关数据结构。 得到 bookmark 数据后,我们可以将它们保存起来,以供下次启动的时候使用:

NSURL.writeBookmarkData(bookmark, toURL: bookmarkSavedURL, options: 0)

大家注意到没有,bookmark 本身也是写入到文件系统中的。但它也是有可能被移动的,所以这个处理我们还需留意。

在下次打开 App 的时候,我们可以将 bookmark 的数据还原出来:

NSURL(byResolvingBookmarkData: bookmarkData, options: .WithoutUI, relativeToURL: nil, bookmarkDataIsStale:nil)

bookmark 的方式可以保证我们引用资源的安全性。 比如引用的文件被移动,甚至被替换,它都可以发觉到。 所以,如果你的 App 需要这种能力的话, 那么 bookmark 肯定是首选方案, 而不用自己费力的去实现了。

结尾

今天跟大家探讨的内容不多,都是关于 NSURL 的一些特性和能力。虽然都是细节的东西,但可能大家反而容易忽略掉他们,比如 NSURL 的 bookmark 特性,相信很多即便有几年经验的同学可能都未必了解。 总之呢,虽然这些特性不一定用得到,但如果有一天需要这些能力的时候,就可以马上想起他们并很快的解决问题啦。


如果你觉得这篇文章有帮助,还可以关注微信公众号 swift-cafe,会有更多我的原创内容分享给你~

本站文章均为原创内容,如需转载请注明出处,谢谢。
关注微信公众号
发现更多精彩
swift-cafe