Tag Archives: apple

Calling a REST service from Swift — a quick example

I figured this would be a recurring theme, so thought I’d write it down for posterity, not least so I didn’t lose it. The scenario is a common one — we have a mobile app for iOS written in Swift where in response to some kind of user trigger we need to go off to the server to do some work via a REST endpoint using JSON as our protocol format. Here’s a snippet I created to do exactly this, a variation on a couple of similar examples but with a couple of notes of things I found along the way.

Let’s assume we’re in a simple View Controller where we’re responding to stimulus from the user in the form of a button. I have an action handler called getData to respond to a button push.

@IBAction func getData(sender: AnyObject) {
   dispatch_async(dispatch_get_main_queue(), {
      self.getJsonData()
   })
}

You will notice a couple of things. Firstly we’re calling a another function on the controller that will actually do the heavy lifting. I’ve separated that out purely to make things easier to read and follow. The second thing is that I’m using the Grand Central Dispatch mechanism in Swift to spin off the action into a separate thread. This follows general good practice for user interface that you shouldn’t do work on the main thread that might block for some period of time, such as writing to the network or disk. Doing so could cause your app to hang and potentially be shut down by iOS as being unresponsive as a result (Apple themselves explain this nicely).

So now to the main guts of the code. In my simple case here I’m doing an HTTP GET of a JSON feed that returns an array of items that looks a bit like this:

[
  {
    "device": "TEST",
    "event": "Testing",
    "date": "2014-08-12T08:31:25.449Z",
    "_id": "53e9d0ddf5d6a92100b8254c"
  },
  {
    "device": "TEST",
    "event": "Testing2again",
    "date": "2014-08-12T09:25:25.062Z",
    "_id": "53e9dd85f5d6a92100b8254d"
  }
]

Here’s the function that does the work of going off to the server to get the feed.

func getJsonData() {
   var urlPath = "http://myserver/myaudits"
   var url = NSURL(string: urlPath)
        
   var session = NSURLSession.sharedSession()
   var task = session.dataTaskWithURL(url!, 
      completionHandler: {
         data, 
         response, 
         error -> Void in
         
            println("Task completed")
           
            if(error != nil) {
                println(error.localizedDescription)
            }
            var err: NSError?
            
            var results = NSJSONSerialization.JSONObjectWithData(data, 
               options: NSJSONReadingOptions.MutableContainers, 
               error: &err) as NSArray
            
            if(err != nil) {
                println("JSON Error \(err!.localizedDescription)")
            }

            println("\(results.count) JSON rows returned and parsed into an array")
            
            if (results.count != 0) {
                // For this example just spit out the first item "event" entry
                var rowData: NSDictionary = results[0] as NSDictionary
                var deviceValue = rowData["device"] as String;
                println("Got \(deviceValue) out")
            } else {
                println("No rows returned")
            }
        })
        
   task.resume()
}

Note that I’m explicitly casting the parsed JSON as an NSArray. One thing I discovered is that Swift isn’t massively tolerant if you get this wrong, for example if the JSON resolves to an Object, then you need to cast to an NSDictionary. Rather than return a useful message, it simply crashed the app. Now of course this was due to a genuine developer gaffe, but still it soaked up a fair amount of time trying to work out what was wrong.

With that, you should be all set. Hope this is useful.

Advertisements

Configuring the Raspberry Pi to share a Mac’s internet connection

One of the great things you can do with a Mac is share your internet connection, and I’ve found this particularly invaluable for doing development with my Raspberry Pi, and especially when I want to take it somewhere to show people. Normally it connects to my home router where I can configure the router to have a static IP address so I know where to find it and off I go, not so easy when you’re mobile.

There are a number of articles out there claiming to show you how to make it all work when you Google for it, but it still took me a fair bit of puzzling and piecing of the bits together to come up with something that worked. So, to save you that trouble, I’m recording my configuration here.

First set up your ethernet adapter

The mechanism I’m using to connect my Mac (Macbook Pro Retina running OS X Mavericks 10.9.5) is via good old Ethernet. For this you’ll need the (rather expensive) Thunderbolt to Ethernet adapter if your Macbook (like mine) doesn’t have an onboard Ethernet socket. You can get cheaper non-Apple alternatives but I’ve no experience of whether they work or not. Once plugged in, open up System Preferences, and then Network. You’ll notice your Ethernet port appears on the list of adapters on the left hand side. You can give the configuration a name of its own, I’ve imaginatively called mine “Raspberry Pi Ethernet (home)” as you can see below.

Screen Shot 2014-10-14 at 15.49.52Now of course DHCP would be fine, and whilst you can probably guess at which IP the Mac’s DHCP server will give you each time, it’s more predictable to have a static IP defined, particularly when running your Pi in “headless” mode. There are therefore some settings we need to set up to make this hang together, not least a static IP configuration for the Mac as it will appear to the Pi so we can use it as our IP gateway. As in the above picture, use the following settings:

  • Configure IPv4: Manually
  • IP Address: 192.168.2.1
  • Subnet mask: 255.255.255.0

Because we’re using a static configuration, we now need to set the DNS server settings ourselves. Without any DNS servers set, the Ethernet connection (and therefore the Pi) will not be able to resolve any of the domain names we throw at it.

Click the Advanced… button, then the DNS tab and then the + button to add a DNS server entry.

Screen Shot 2014-10-14 at 15.59.09

You can simply lift the DNS settings from your Wifi configuration (provided of course your wifi is already up and happily resolving!) or indeed use some public DNS server settings. I’ve got a mix of public DNS, a couple from work and my home router. Click OK when you’re done to save the settings.

NOW TURN ON INTERNET SHARING

Having set up the Ethernet port, we now need to tell the Mac we want to share the wifi internet connection with devices connected via Ethernet. It couldn’t be easier — back to System Preferences, select Sharing and tick Internet Sharing. Select Wi-fi and Thunderbolt Ethernet as the points where you want to share from and to as per the screenshot below.

Screen Shot 2014-10-14 at 16.06.29

 

NOW CONNECT AND CONFIGURE THE PI

I was surprised how resilient the local configuration between the Mac and the Pi was when I was fiddling with these next steps. Getting the Mac and the Pi to see each other is the easy bit, the harder bit was making the Pi be able to see the internet beyond. Apple have made things easier still by making the Ethernet adapter work out when you’re using it to connect to another machine and automatically flipping into “crossover” mode so you can connect the Pi with bog standard Ethernet cable. Connect the Pi to the Mac’s Ethernet adapter and start it up.

First time of asking the Pi will be assigned an IP of 192.168.2.2 by the Mac’s DHCP server (assuming your Pi by default is set up for DHCP from the Ethernet port). I’ve not tested the theory of whether that ever changes, but to make absolutely sure (and certainty is definitely preferred when doing demos) we will configure the Ethernet adapter with static settings based on the Mac’s configuration. Once the Pi is started, connect via SSH from the Mac and once logged in and on the command prompt, enter the following command:

sudo vim.tiny /etc/resolv.conf

This will open the Vim editor (same commands as Vi). You want a single line it as follows:

nameserver 192.168.2.1

This tells the Pi to use the Mac as its DNS server, rather like you might expect with a connection to a home router.
Having saved the changes, we now need to set the static configuration for the Ethernet port. We’ll use Vim again, this time enter the following command:

sudo vim.tiny /etc/network/interfaces

This time there are a few more lines to add. If you want to make sure you don’t forget your existing Ethernet settings, you can comment them out with a hash. Otherwise, your settings should look as follows:

auto eth0
iface eth0 inet static
address 192.168.2.2
netmask 255.255.255.0
gateway 192.168.2.1

This tells the Pi to adopt the 192.168.2.2 address permanently using the Mac as the IP gateway with corresponding subnet mask.

You’re now all set. For good measure, restart the Pi and all the changes should stick.

The Proof in the PUDDING (or PI)

In my case I’ve been using TightVNC to access the Pi’s desktop, so as a crude test that everything was hunky dory I simply open up my Midori browser and try and hit the public internet. For posterity, everything looks as it should when I try and hit this blog:

Screen Shot 2014-10-14 at 16.29.13