神刀安全网

Creating and Modifying an NSURL in your Swift App

In many types of apps, you have to access files.  They can be in your app bundle, on the file system, or even somewhere on the web.  You need to have someway to refer to where they are in your code.  On Apple platforms, you basically have 2 choices, as a String or an NSURL.

Given the address bar right above you, or any use of a terminal, a Swift String would be a very understandable choice, I mean, that’s all that text is in the address bar, right?  Many of the older APIs in the Cocoa and Cocoa Touch SDKs take NSURLs and Strings (referred to as a “path” in those APIs usually), but things are moving more and more towards just using NSURL everywhere.  NSURL has many advantages over String paths, most notably that you can access different parts of the URL from properties, instead of having to write your own code to parse those components from the path String.

Stay tuned as we learn a thing or two about creating and using NSURL in your Swift app.

Creating an NSURL in Swift

There are several initializers and factory methods to create an NSURL in Swift, but I’m going to cover some of the more useful ones.

init?(string URLString: String)

This one is the most plain, and probably the most used.  This takes your Swift String version of a URL, and changes it into an NSURL object.  It is a failable initializer, because not all strings can make valid URLS.  There are some characters that cannot be used in URLs, and thus are percent encoded, meaning a code that CAN be sent in a URL is used in its place.  The one I personally have seen the most is %20, the “space” character.  This initializer expects only valid characters, it will not percent encode for you.  If the string does have characters or anything that can’t be converted into a valid URL, this initializer will return nil.

Swift

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

This is actually a convenience initializer which defers to the initializer below.

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

This is the dedicated initializer.  Similar to the previous initializer, it is a failable one, and takes a similar URL Swift String, but it also takes an optional baseURL object, which is an NSURL itself.  If the baseURL is nil, it just makes the URL entirely from the URLString, which is probably what the first initializer does under the hood.

Swift

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

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

This is similar to the above initializer, but is meant to point at a local file or directory.  I’m not certain why there is a special version for local files, but I presume some optimizations are made (at least to start it with the file scheme, as opposed to http, or other ones).  There is a version without the isDirectory parameter, but the header file suggests using this one if you do know whether it is a directory or not.  Presumably, the other one will need to perform the check itself, while this one has you providing the answer, saving it from having to check.

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

Newly added in iOS 9, this is similar to the previous one, but with the relativeToURL parameter.  Like the previous initializers, this will return an NSURL that appends the path to the baseURL.  This could be used, if you had a directory of several files, where you were iterating through them to use for something.  You could supply the directory the files were in as the baseURL, and then just create the URLs with the file name as the Swift String path.

Converting URL back to a Swift String

Sometimes, especially when dealing with older API, or when showing it to the user, you need to convert an NSURL back to a Swift String.  Thankfully, NSURL provides a simple read-only property to get that out:  absoluteString.  Just call that property on your NSURL object and you’ve got it:

Swift

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

In this case it took our article constant that we defined using the relativeToURL version of the initializer, resolved it into a complete URL from scheme until the end (which in this case is a path).  If we did have file extensions, queries, and fragments on this URL, it would resolve them as well.  The original article object was returned from the failable initializer, so that is why we still have that question mark there for Swift’s optional chaining.

Modifying an NSURL

Each of these functions return a new NSURL based on the one it was called from, but with the requested modification done.  They do NOT change the NSURL they are called from though, it remains the same.

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

This one adds more path components to the URL, say if you were adding a file to the directory you’re in (which is stored in the NSURL this is called from).  There is a version without the isDirectory parameter like some of the initializers, but if you know whether it is a directory or not, it is recommended to use this one to save the metadata check to determine whether it is a directory or not.

var URLByDeletingLastPathComponent : NSURL ? { get }

This property will return a new NSURL with the last path component deleted.  This works on the path part of a URL, so other areas of the URL are unaffected, like the domain.  So we can do this:

Swift

let articleTwo = NSHipster?.URLByAppendingPathComponent("ios9", isDirectory: true) //articleTwo now contains "http://nshipster.com/ios9/"  let deletePathComp = articleTwo?.URLByDeletingLastPathComponent //deletePathComp now contains "http://nshipster.com/"
let articleTwo = NSHipster?.URLByAppendingPathComponent("ios9", isDirectory: true) //articleTwo now contains "http://nshipster.com/ios9/"   let deletePathComp = articleTwo?.URLByDeletingLastPathComponent //deletePathComp now contains "http://nshipster.com/" 

If there is no path information, things can get a bit weird.  For fun, I chained a few URLByDeletingLastPathComponent afterwards, and it ended up just appending “../” afterwards, analogous to going up a directory in the command line (cd ..).

There are several more modification methods and properties, but these are probably the most commonly used.

Conclusion

If you are curious about specifics of URL formatting specifications, you can checkout the RFC documents that Apple’s NSURL Class Reference mentions in how it handles URLs.  The strings used when initializing URLs must conform to RFC 2396 , and the URLs themselves are parsed according to RFC 1738 and RFC 1808 .  The are pretty long but probably have anything you would want to know about URLs, URIs, etc.

There are many other properties in NSURL if you want a fully resolved NSURL, the baseURL, host, query, fragment, etc, and you can check them out in Apple’s NSURL Class Reference, but I personally primarily use absoluteString, and occasionally pathExtension.

I hope you found this article helpful.  If you did, please don’t hesitate to share this post on Twitter or your social media of choice, every share helps.  Of course, if you have any questions, don’t hesitate to contact me on theContact Page, or on Twitter  @CodingExplorer , and I’ll see what I can do.  Thanks!

Sources

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Creating and Modifying an NSURL in your Swift App

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮