Some time ago I wrote a post about how to install Swift, the language developed by Apple to build software for his OS X, and iOS systems, on Debian Linux.

Of course, once I had Swift installed in my computer the real question became: how far can I get with Swift on Linux? what kind of applications could I build? In order to answer that question I decide to start building a simple script: a REST client that would send data to an Azure based mobile service.

On Swift 3, and Foundation

The first time I installed Swift on my Debian Jessie box I went with Swift 2. The reason was quite simple: the swift 3 binaries required libraries newer than the ones available for Debian Jessie, so it was simpler to just install the swift 2 binary fully compatible with the version of Debian that I was using.

That works fine for people that want to get introduced to Swift, and learn how the language work. The problem is that to build useful software you need a bit more than just the standard Swift Library: you will want to have also the Foundation framework for networking, and file manipulation.

The good news are that there is a Foundation implementation for Linux, the bad news, for me, were that it was not included in the Swift 2 binaries, so I had to move to Swift 3.

The bottom line is that any attempt to run a Swift script that uses the Foundation framework in a Linux box using the swift 2 binaries will result in this error:

error: no such module ‘Foundation’

Status of the Foundation module in Linux

The foundation module for Linux is not finished: there are features that haven’t been ported yet. Here is an example of I what I mean:

let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("\(error)")
return
}

This code will result in the following error:

fatal error: shared is not yet implemented: file Foundation/NSURLSession/NSURLSession.swift

Here you can check the status of the implementation

Doing REST in Swift 3 from my Linux box

Despite the above difficulties, and having verified that Swift development in Linux has ,at this point, some limitations lets go back to the original goal of this post: write some swift code in a Linux machine that will send data to an Azure mobile web service.

For starters, since  I am going to be doing REST calls, I will import the foundation module to be able to use the URLSession, and URLRequest classes in my code.

import Foundation

let headers = [
  "zumo-api-version": "2.0.0",
  "content-type": "application/json"
]

let parameters = [
  "isbn": "8497939468",
  "title": "Dracula",
  "date_publication": "01-27-2009"
] as [String : Any]

let postData = try! JSONSerialization.data(withJSONObject: parameters, options: [])

let url = URL(string: "http://sometestservice.azurewebsites.net/tables/books")!
var request = URLRequest(url: url)

request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let sessionConfiguration = URLSessionConfiguration.default;
let urlSession = URLSession(
                configuration:sessionConfiguration, delegate: nil, delegateQueue: nil)
let dataTask = urlSession.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  guard let data = data, error == nil else {
    print("Error: \(error?.localizedDescription)")
    return
  }
  if let httpStatus = response as? HTTPURLResponse {
        if httpStatus.statusCode == 201
        {
            print("Data inserted correctly")
        }
        else
        {
            print("Unexpected response:\(httpStatus.statusCode)")
        }
  }
  print("operation concluded")
})

dataTask.resume()

print("Wait for server response, and press enter to exit")
let _ = readLine(strippingNewline: true)

The snippet above is doing a POST request to web service to add an item book (represented by a ISBN, title, and publication date) to the server. The program checks for errors, and if the server returns a 201 (indicating that the object was successfully created) informs the user that the operation has been successful.

Some of the stuff was necessary because of my choice of Azure as the backend (such as the inclusion of the “zumo-api-version” in the headers):

let headers = [
  "zumo-api-version": "2.0.0",
  "content-type": "application/json"
]

The following lines were added to prevent the program from exiting before the server had sent a response:

print("Wait for server response, and press enter to exit")
let _ = readLine(strippingNewline: true)

I also had to do some adjusting to my initial code when I run into some functionalities not implemented yet in Foundation, but in the end I could manage with the implemented ones, and the data made it happily to the server 🙂

Conclusions

Swift in Linux is still a work in progress, and although it is good enough for learning, and playing around, it still has a long way to go to be really usable (although the situation has been slowly improving since it first release, as more functionality are implemented in the  swift core libraries)

I would also recommended installing an editor like Visual Code, or Atom, if you intend to do some Swift developing on Linux.

So what do you think of Swift on Linux?

Advertisements