Swift 4 の URL は -[NSURL fileReferenceURL] に非対応
- Apple
- 開発
-[NSURL fileReferencceURL] を使用すると AppleScript でいうところの alias みたいな1、ファイルの場所に依存しない特別な URL を取得できる。
NSURL* url = [NSURL fileURLWithPath: @"/Applications/"]; //1
url.fileReferenceURL //2
1: file:///Applications/
2: file:///.file/id=3534367.8613694728/
これを Swift で使うのが今回の話。
Swift から呼ぶと
Swift で同じ内容を書いてみる。まず期待を裏切られるのは URL に対して「fileRe」まで入力しても補完されないことだ。...どうやらこの機能は NSURL にしか用意されていないらしい。
まあ焦ることもない。NSString の機能を使いたいときと同じように as NSURL してから呼べばすべて解決するだろう。
import Foundation
let url = URL(fileURLWithPath: "/Applications/") //1
let fileReferenceUrl = (url as NSURL).fileReferenceURL() //2
1: file:///Applications/
2: Optional(file:///Applications/)
プロパティ扱いになっていないようで () が必要なのが気持ち悪いくらいか。クラッシュせずに動くし、解決!
...してない。これよく見ると普通の URL じゃないか!
変換できない
調べてみると、どうやら fileReferenceURL というのは一瞬でも Swift の URL に変換したら通常の URL に変化してしまうらしい。普通に呼んだだけなのに失敗した理由は何かというと、このメソッドは NSURL のものであるけれど Swift 上では返り値の型が URL? なのでそこで変換されてしまったということか。
Workaround
対処法は、 Swift による変換が入らないようにすることだ。以下のように as NSURL? をつけるのが正解。似てるけど as? NSURL はダメだから注意しよう。
let url = URL(fileURLWithPath: "/Applications/") //1
if let fileReferenceUrl = (url as NSURL).fileReferenceURL() as NSURL? {
fileReferenceUrl //2
}
if let fileReferenceUrl = (url as NSURL).fileReferenceURL() as? NSURL {
fileReferenceUrl //3
}
1: file:///Applications/
2: file:///.file/id=3534367.8613694728/
3: file:///Applications/
Swift の URL が対応しないのは目をつぶるにしても、せめて型が NSURL? になるように修正してほしいものである...
保存するなら
Apple の説明によると、この fileReferenceURL は特定のタイミングで無効になる値らしい。保存するなら Bookmark Data を作成する必要があるそうだ。
A file reference URL's path should never be persistently stored, because it is not valid across system restarts or remounts of volumes. If you need to store a persistent reference to a file system object, use a bookmark instead. You can create a bookmark by calling bookmarkData(options:includingResourceValuesForKeys:relativeTo:).
-
よく調べずに書いたが本当? ↩︎
Share
リンクも共有もお気軽に。記事を書くモチベーションの向上に役立てます。