post-photo

If you’re a mobile developer, there’s a pretty good chance that you’ve used some kind of networking. Apps most often use a REST API, and usually it’s enough, as it allows fast and easy JSON based communication (here is a JSON object converter). One of the downsides is, however, that REST communication requires the client to initialize the requests, the server only responds to them. Push notifications exist, it’s true, but their purpose is rather different, and they are also kind of unreliable.

So what if we decide to write an app that utilizes real time communication, like a chat room? Our goal is clear: Find a way to send messages to the clients from the server, and directly.

The answer: Web sockets.

text

Get Started with Web Sockets

The technology has been around for a while, and there are several libraries that help us manage socket connections. Some examples are Starscream, Jetfire, PocketSocket, and SwiftWebSocket. I haven’t actually tried all of them, and the ones I have are pretty similar to each other.

In this short tutorial we’re going to use SwiftWebSocket, which is available here. It’s probably the easiest to use, and excellent for demonstration purposes. In case you’re wondering, it has a sibling for Objective C, but let’s stick with Swift for now. I recommend installing it via CocoaPods (pod‘SwiftWebSocket’), but you can just as easily download and add it to your project manually.

You should be familiar with the Swift language and general iOS concepts, because we’re not going into too much detail about project setup. Instead, the focus will be on…

Socket handling

A websocket is basically a protocol, that allows us to manage a full duplex connection over TCP. Unlike HTTP, the connection stays open, allowing the participants to keep sending messages. But let’s not dwell on it too much, this library is actually pretty easy to use.

Programatically, each of these connections are represented by a websocket, which can be instantiated as follows:

let socket = WebSocket("wss://echo.websocket.org")

That wasn’t really hard, was it? In this example, we use the echo server, as it’s public and accessible to everyone. It has very basic functionality. You can try it out in your browser too, on this page.

It’s useful (quite necessary, in fact) to keep the socket as a property, as you’re going to use it from other methods.

Next, we specify how to handle the socket’s events:

socket.event.open = {
    print("opened")
}
 
socket.event.close = { code, reason, clean in
    print("closed")
}
 
socket.event.error = { error in
    print("error \(error)")
}
 
socket.event.message = { message in
    if let text = message as? String {
        self.handleMessage(text)
    }
}

As you can see, there aren’t many events to observe. We could place a lot more logic inside these functions, it’s up to you how to handle them. The main part is about the handleMessage method.

Handling received messages

The echo website sends any message back we send. That’s all good, but in a proper application, messages are a bit more complex. In a chat app, we’d require the received message to contain the sender, time of sending, and the actual chat text. You should set up your server to format these messages in a way that’s easy to process (for example, JSON). Here’s an example how to parse a JSON message from the server:

func handleMessage(jsonString:String){
    if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding){
        do {
            let JSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments)
            print("We've successfully parsed the message into a Dictionary! Yay!\n\(JSON)")
        } catch let error{
            print("Error parsing json: \(error)")
        }
    }
}

Of course, we can test it: Let’s send a formatted JSON message to the echo server, then we can parse the answer. First, we’re going to need some UI for the testing, let’s set it up!

Create a new Single View Application in XCode for any device (we don’t need tests or Core Data at the moment). All we need is one ViewController, with a UI like this:

text

Add the SwiftWebSocket library to your project (don’t forget to close XCode and open the workspace file if you’re using CocoaPods). All that’s left is to connect the UI elements to our ViewController, and some coding.

First, our properties:

@IBOutlet weak var nameField: UITextField!
@IBOutlet weak var messageField: UITextField!
var socket : WebSocket!

If you added the library through CocoaPods, import it as “import SwiftWebSocket“! If You get an error saying that it can’t be found, just clean your project, and it should be fine (CocoaPods does that sometimes).

In the viewDidLoad method, instantiate the websocket and add the event handling code (as seen above). Don’t forget to assign the socket and open it!

socket = WebSocket("wss://echo.websocket.org")
  
... Event observing for open, close, error and message ...
  
socket.open()

Add the handleMessage method to the ViewController, now all that’s left is actually sending a text. Since we expect the server to send us JSON formatted messages, we’re going to create just that. Copy this method into your class and connect it to your button’s “Touch Up Inside” event.

@IBAction func sendTapped(sender: AnyObject) {
    var json = [String:AnyObject]()
    json["name"] = nameField.text
    json["message"] = messageField.text       
 
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "HH:mm"
    json["time"] = dateFormatter.stringFromDate(NSDate())       
 
    do {
        let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted);
        if let string = String(data: jsonData, encoding: NSUTF8StringEncoding){
            socket.send(string)
        } else {
            print("Couldn't create json string");
        }
    } catch let error {
        print("Couldn't create json data: \(error)");
    }
}

That’s it! Build and run your application (iOS Simulator works fine), enter some text into the fields, then hit Send. You should receive your “answer” from the echo server instantly, containing the JSON string that we just sent. For now, it only shows up in the console, but since we’ve already parsed the message into a Dictionary, why not do something with the contents? Let’s modify the handleMessage method to give some feedback to the user!

func handleMessage(jsonString:String){
        if let data = jsonString.dataUsingEncoding(NSUTF8StringEncoding){
            do {
                let JSON : [String:AnyObject] = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! [String : AnyObject]
                print("We've successfully parsed the message into a Dictionary! Yay!\n\(JSON)")
                let sender : String = JSON["name"] as! String
                let message : String = JSON["message"] as! String
                let time : String = JSON["time"] as! String               
 
                let alert = UIAlertController(title: "Message!", message: "\(sender)(\(time)): \(message)", preferredStyle: .Alert)
                alert.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: nil))
                self.presentViewController(alert, animated: true, completion: nil)
            } catch let error{
                print("Error parsing json: \(error)")
            }
        }
 
    }

JSONObjectWithData returns an object of type AnyObject, so we need to explicitly cast it to [String:AnyObject] in order to access its contents. Try it out now! Talking to ourselves is a bit weird, but right now it’s also satisfying.

text text

Going forward

Websockets are awesome, huh? Chat rooms are only the beginning, there’s potential for websocket applications in a lot of topics (card games, for one). I hope this short guide gave you some insight, I strongly encourage you to experiment and play with this library, there is a huge number of possibilities! You should also try other libraries (the ones listed above, for example). You’ll see that their basic functionality is very similar, so pick the one that suits your coding style best.

Parsing messages into Dictionaries is cool, but it’s only the first step. You might want to store the information in your own classes, for convenience and safety. That’s where JSON parsing libraries come in. I have an article about a select few, so give them a shot! They are simple and powerful tools to power up your apps.

If you are interested in building your own WebSocket server, check out our article written by Süxy! If you need to know even more, get to WebSockets on Android.

Until then, have fun!

This is a post published on #wanarileaks, a tech blog powered by Wanari. We are a custom software development company, headquartered in Budapest. We love building awesome products that bring the users a stress-free experience. Let us know if you enjoyed this post and click here if you’d like to learn more about us.

member photo

His Wanari career started in October 2013, he is not only an experienced iOS developer, he also has excellent English skills to explain his stuff.

Latest post by Tamás Keller

Everything You Need to Know About JSONJoy, SwiftyJSON & OCMapper