如何在Swift中获取文件引用URL?

如何在Swift中获取文件引用URL?,swift,cocoa,filesystems,nsurl,Swift,Cocoa,Filesystems,Nsurl,我无法获得在Swift中工作的文件引用URL。首先,Swift的URL类型甚至没有定义将文件路径URL转换为文件引用URL的方法NSURL有这样一个方法:fileReferenceURL()->URL?,但我不知道如何让它工作 我尝试的是: let myURL = URL(string: "file:///Users/Me/Desktop/CoolFolder")! let refURL = (myURL as NSURL).fileReferenceURL()! NSLog("\(myURL)

我无法获得在Swift中工作的文件引用URL。首先,Swift的
URL
类型甚至没有定义将文件路径URL转换为文件引用URL的方法
NSURL
有这样一个方法:
fileReferenceURL()->URL?
,但我不知道如何让它工作

我尝试的是:

let myURL = URL(string: "file:///Users/Me/Desktop/CoolFolder")!
let refURL = (myURL as NSURL).fileReferenceURL()!
NSLog("\(myURL)")   // file:///Users/Me/Desktop/CoolFolder (ok)
NSLog("\(refURL)")  // file:///Users/Me/Desktop/CoolFolder (wha?!?)
logFolderContents() // Logs contents of folder pointed to by refURL
// ...
// Rename CoolFolder -> UncoolFolder in Finder.
// ...
logFolderContents() // Fails!
// ...
// Rename UncoolFolder -> CoolFolder.
// ...
logFolderContents() // Successfully logs contents again.
基本上,
refURL
继续指向原始文件路径。调用
fileReferenceURL()
似乎什么也没做

如何在Swift中获取文件引用URL

更新:
User@Sam在评论中指出,这似乎是一个Swift 3回归错误,如本文所述:。请访问该链接并对此错误进行投票。该线程还包含一个变通方法。

遗憾的是,截至2021年4月,该错误仍未修复。这使得比较文件URL是否相等相当困难

对于ObjC,这一点非常有效:

NSString *p1 = @"/etc/hosts";
NSString *p2 = @"/private/etc/hosts";
    
NSURL *url1 = [NSURL fileURLWithPath:p1];
NSURL *url2 = [NSURL fileURLWithPath:p2];
    
NSURL *ref1 = url1.fileReferenceURL;
NSURL *ref2 = url2.fileReferenceURL;
    
BOOL equal = [ref1 isEqual:ref2];
在Swift中,我得到了与以下代码几乎相同的结果(即,64位包含卷ID和文件ID):

let p1 = "/etc/hosts"
let p2 = "/private/etc/hosts"

let url1 = URL(fileURLWithPath: p1)
let url2 = URL(fileURLWithPath: p2)

// This does not work because the refs do not use fileIDs as they should
// See https://bugs.swift.org/browse/SR-2728
let ref1bad = (url1 as NSURL).fileReferenceURL()!
let ref2bad = (url2 as NSURL).fileReferenceURL()!
let equalBad = ref1bad == ref2bad
print("\(ref1bad) = \(ref2bad): \(equalBad)")

// This works:
var ref1: NSObject?
var ref2: NSObject?
if let resourceValues = try? url1.resourceValues(forKeys: [.fileResourceIdentifierKey]) {
    ref1 = resourceValues.fileResourceIdentifier as? NSObject
}
if let resourceValues = try? url2.resourceValues(forKeys: [.fileResourceIdentifierKey]) {
    ref2 = resourceValues.fileResourceIdentifier as? NSObject
}
let equal = ref1!.isEqual(ref2) // the use of "!" is probably not good here
print("\(String(describing: ref1)) = \(String(describing: ref2)): \(equal)")

如果您想要一个真正的文件引用URL,那么必须从对象中的两个32位值(看起来是
NSData
类型)重构URL,并使用第一个作为文件ID,第二个作为卷ID。但是,为它编写代码超出了我目前相当贫乏的Swift技能。

你希望
refURL
有什么价值?我希望它看起来像这样:file:///.file/id=6571367.2773272/. 文件引用URL不包含路径名,而是唯一的ID。当路径名更改(资源被重命名或移动)时,ID仍然指向同一资源。作为测试,请将第一行更改为:
let myURL=URL(fileURLWithPath:“/Users/Me/Desktop/CoolFolder”)
@rmaddy相同的结果。看起来这是一个已知的错误:感谢您继续回答这个老问题。我之前基本上放弃了Swift,部分原因是这个问题。一旦成熟了,也许有一天会再来。是的,Obj-C。