Thursday, June 4, 2015

How would you pull data from a server in swift?


Pulling data from the server was very common task on iOS. As far as I know, there are 2 frameworks NSURLConnection and NSURLSession allows fetch data from the servers. My goal is download a mp3 file from server and save to Document directory. Most of code are using NSURLSession and NSFileManager.

First of all, the URL for save this mp3 file must be inside Document directory. url wrapped around lazy var

lazy var localMp3URL: NSURL = {
    let fileManager = NSFileManager.defaultManager()
    let documentURLs = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    let docURL: NSURL = documentURLs.last as! NSURL
    let fileURL = docURL.URLByAppendingPathComponent("movie_quote.mp3")
    return fileURL
}()

Let's check mp3 file for existence, because we do not want download file too many times

let fileManager = NSFileManager.defaultManager()
if (fileManager.fileExistsAtPath(localMp3URL.path!) == false) {
    downloadMp3()
}

NSURLSession has designed for multiple tasks execute concurrently. Therefore we needs create a shared session and task.

var urlSession: NSURLSession!

let conf = NSURLSessionConfiguration.defaultSessionConfiguration()
self.urlSession = NSURLSession(configuration: conf)

to create a download task

func downloadMp3() {
        
   let remoteURL = NSURL(string: "https://s3.amazonaws.com/udacity-hosted-downloads/ud585/audio/movie_quote.mp3")
        
   let dlTask = urlSession.downloadTaskWithURL(remoteURL!) { location, response, error in
       if (error == nil) {
           let res = response as! NSHTTPURLResponse
           if (res.statusCode == 200) {
               let fileManager = NSFileManager.defaultManager()
                    
               var error: NSError?
               if (fileManager.moveItemAtURL(location, toURL: self.mp3URL, error: &error) == false) {
                   println(error)
               }
          }
          else {
              println(res)
              let desc = NSHTTPURLResponse.localizedStringForStatusCode(res.statusCode);
              println(desc)
          }
      }
      else {
          println(error)
      }
   }
   dlTask.resume()}

Download function was quiet complicated because there are a lot of failures might be occurs. The code shown here to demonstrate how NSURLSession work. Do not take this into production.