{"id":16521,"date":"2016-12-02T14:19:14","date_gmt":"2016-12-02T19:19:14","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=16521"},"modified":"2019-01-08T13:39:25","modified_gmt":"2019-01-08T18:39:25","slug":"file-reference-urls-dont-work-in-swift-3","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2016\/12\/02\/file-reference-urls-dont-work-in-swift-3\/","title":{"rendered":"File Reference URLs Don&rsquo;t Work in Swift 3"},"content":{"rendered":"<p><a href=\"https:\/\/bugs.swift.org\/browse\/SR-2728\">SR-2728<\/a>:<\/p>\n<blockquote cite=\"https:\/\/bugs.swift.org\/browse\/SR-2728\">\n<p>In Swift 3.0 (i.e. Xcode 8.0 or Xcode 8.1 beta 1), a call to <code>fileReferenceURL<\/code> does <em>not<\/em> give a file reference URL anymore... this code<\/p>\n<pre>import Foundation\nlet string = \"file:\/\/\/Users\/admin\"\nif let url = NSURL(string: string) {\n  if let ref = url.fileReferenceURL() {\n    print (\"ref = (ref)\")\n  }\n}\n<\/pre>\n<p>prints<\/p>\n<pre>ref = file:\/\/\/Users\/admin\/<\/pre>\n<p>while it should have been printing<\/p>\n<pre>ref = file:\/\/\/.file\/id=6571367.437879\/<\/pre>\n<p>as it did, correctly, in Swift 2.2 (and before) in Xcode 7.3.1 for example.<\/p>\n<\/blockquote>\n<p>Via <a href=\"http:\/\/lists.apple.com\/archives\/cocoa-dev\/2016\/Nov\/msg00158.html\">Charles Srstka<\/a>:<\/p>\n<blockquote cite=\"http:\/\/lists.apple.com\/archives\/cocoa-dev\/2016\/Nov\/msg00158.html\"><p><code>.fileReferenceURL<\/code> doesn&rsquo;t exist on <code>URL<\/code>. It does exist on <code>NSURL<\/code>, but thanks to the bridging magic it returns a <code>URL<\/code>, which the ObjC-Swift bridge turns into a normal file path URL.<\/p><\/blockquote>\n<p>Fr&eacute;d&eacute;ric Blondiau has <a href=\"https:\/\/bugs.swift.org\/secure\/attachment\/11214\/11214_Workaround.pdf\">some<\/a> <a href=\"https:\/\/bugs.swift.org\/secure\/attachment\/11218\/11218_Workaround+V2.pdf\">workarounds<\/a>, but these are distasteful to me because they rely on the internal details of both <code>NSURLFileResourceIdentifierKey<\/code> and <a href=\"http:\/\/stackoverflow.com\/q\/14665522\/6311\">file reference URLs<\/a>.<\/p>\n<p>It seems like the proper short-term solution would be to write some Objective-C code to return an object that is not bridged to <code>URL<\/code>. This could probably be the actual <code>NSURL<\/code> typed as <code>id<\/code>. Or, if you&rsquo;re going to use an opaque token anyway, another option would be to store bookmark data. I assume that would be slower, though.<\/p>\n\n<p id=\"file-reference-urls-dont-work-in-swift-3-update-2018-09-08\">Update (2018-09-08): <a href=\"https:\/\/christiantietze.de\/posts\/2018\/09\/nsurl-filereferenceurl-swift\/\">Christian Tietze<\/a>:<\/p>\n<blockquote cite=\"https:\/\/christiantietze.de\/posts\/2018\/09\/nsurl-filereferenceurl-swift\/\"><p>Swift 4.1 has a simpler mechanism to ensure you get a <code>NSURL<\/code> instead of a <code>URL<\/code> &#x2013; the only type that supports file reference URLs as of September 2018, still.<\/p>\n<pre>if let fileRefURL = (url as NSURL).fileReferenceURL() as NSURL? { \n    print(fileRefURL)\n}<\/pre>\n<p>Try that in the Swift 4.1 REPL to see that it works. Whew.<\/p><p>I do understand that there may be reasons to remove <code>fileReferenceURL<\/code> from <code>URL<\/code> and leave it on <code>NSURL<\/code>, but when you <em>do<\/em> invoke it on <code>NSURL<\/code>, I think it should at least return another <code>NSURL<\/code> object that works as expected instead of bridging to Swift&rsquo;s <code>URL<\/code> struct that, for some reason, won&rsquo;t work.<\/p><\/blockquote>\n\n<p id=\"file-reference-urls-dont-work-in-swift-3-update-2019-01-08-update-2019-01-08\">Update (2019-01-08): <a href=\"https:\/\/twitter.com\/JensAyton\/status\/1082317738142560256\">Jens Ayton<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/JensAyton\/status\/1082317738142560256\">\n<p>No, wait! It actually crashes when you bridge the file reference <code>NSURL<\/code> to <code>URL<\/code>.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>SR-2728: In Swift 3.0 (i.e. Xcode 8.0 or Xcode 8.1 beta 1), a call to fileReferenceURL does not give a file reference URL anymore... this code import Foundation let string = \"file:\/\/\/Users\/admin\" if let url = NSURL(string: string) { if let ref = url.fileReferenceURL() { print (\"ref = (ref)\") } } prints ref = file:\/\/\/Users\/admin\/ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2018-09-08T19:23:54Z","apple_news_api_id":"f28140d3-230a-4751-a80f-a21ff706c76c","apple_news_api_modified_at":"2019-01-08T18:39:29Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/A8oFA0yMKR1GoD6If9wbHbA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[131,69,31,1380,30,1381,54,71,901,489],"class_list":["post-16521","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-bug","tag-cocoa","tag-ios","tag-ios-10","tag-mac","tag-macos-10-12","tag-objective-c","tag-programming","tag-swift-programming-language","tag-url"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/16521","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=16521"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/16521\/revisions"}],"predecessor-version":[{"id":23881,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/16521\/revisions\/23881"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=16521"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=16521"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=16521"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}