• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • Swift
  • Tech Tips

Swift 2

Protocol Oriented Programming in Swift

March 10, 2016 By Ravi Shankar Leave a Comment

Object Oriented Programming is a paradigm used by programmers many decaded to solve computer problems by modeling them in to classes. In Swift 2.0 a new programming pattern has been introduced known as Protocol Oriented Programming. In this article, we will the three major feature as part of Protocol Oriented Programming

  • Modeling with Protocols and Structs
  • Protocol Extension
  • Swift Standard Library Extension

Using Protocols and Structs

Let us see an example by modeling Bicylce, MotorBike and Car with Protocols and Structs. Create Vehicle and MotorVehicle protocol with the following property definition

[code language=”swift”]protocol Vehicle {
var speed: Int {get}
var color: String {get}
var yearOfMake: Int {get}
}

protocol MotorVehicle {
var engineSize: Int {get}
var licensePlate: String {get}
}
[/code]

In Swift we can make any type (Class. Struct, Enums) to conform to a Protocol. Let us go for a value type (Struct) and not class as we are moving away from inheritance. And it is always safe to use value type and avoid memory related issues by using object references (Class).

[code language=”swift”]struct Bicyle: Vehicle {
let speed: Int
let color: String
let yearOfMake: Int
}

struct MotorBike: MotorVehicle, Vehicle {
let speed: Int
let color: String
let engineSize: Int
let licensePlate: String
let yearOfMake: Int
}
struct Car: MotorVehicle, Vehicle {
let speed: Int
let color: String
let engineSize: Int
let licensePlate: String
let numberOfDoors: Int
let yearOfMake: Int
}[/code]

In the above code snippet, we have created three strutcs Bicycle, MotorBike and Car. Bicyle conforms to Vehicle but Car and MotorBike conform to both Vehicle and MotorVehicle. Now start creating Cars, Bicycles and MotorBikes using corresponding structs.

[code language=”swift”]let cycle = Bicyle(speed: 10, color: “Blue”,yearOfMake: 2011)
let bike = MotorBike(speed: 65, color: “Red”, engineSize: 100, licensePlate: “HT-12345”,yearOfMake: 2015)
let bmw = Car(speed: 220, color: “Green”, engineSize: 1200, licensePlate: “FC-20 435”, numberOfDoors: 4,yearOfMake: 2016)
let audi = Car(speed: 220, color: “Cyan”, engineSize: 1200, licensePlate: “FC-41 234”, numberOfDoors: 4,yearOfMake: 2013)
[/code]

Protocol Extension

In Swift 2.0, the real power Protocol comes with its ability to add extension. It is not just adding method definition but now Protocol allows you to add implemenation as well. Let us say you want to compare vehicles based on yearOfMake attribute. All you need to do is to add an extension for Vehicle Protocol

[code language=”swift”]extension Vehicle {
func isNewer(item: Vehicle) -> Bool {
return self.yearOfMake > item.yearOfMake
}
}
// comparing audi and bmw should return false
audi.isNewer(bmw)[/code]

Swift Standard Library Extension

You can also add extension to Swift standard library such CollectionType, Range, Array etc.. Let us take the following scenario where you have an array of MotorBikes and want to filter them based on licensePlate information.

[code language=”swift”]let bike1 = MotorBike(speed: 65, color: “Red”, engineSize: 100, licensePlate: “HT-12345”,yearOfMake: 2015)
let bike2 = MotorBike(speed: 75, color: “Black”, engineSize: 120, licensePlate: “RV-453”,yearOfMake: 2013)
let bike3 = MotorBike(speed: 55, color: “Blue”, engineSize: 80, licensePlate: “XY-5 520”,yearOfMake: 2012)
let bike4 = MotorBike(speed: 55, color: “Red”, engineSize: 80, licensePlate: “XY-7 800”,yearOfMake: 2009)

let motorbikes = [bike1,bike2, bike3, bike4]
[/code]

How about filtering of all Small Mopeds based on licensePlate containing “XY” characters. This can be achieved by adding an extension to CollectionType which conforms to MotorVehicle protocol. Then create a new function “filterLicensePlate” as shown below

[code language=”swift”]extension CollectionType where Generator.Element:MotorVehicle {
func filterLicensePlate(match:String -> [Generator.Element] {
var result:[Generator.Element] = []
for item in self {
if item.licensePlate.containsString(match) {
result.append(item)
}
}
return result
}
} [/code][code language=”swift”]let motorbikes = [bike1,bike2, bike3, bike4]
// fiter only small mopeds based on XY
motorbikes.filterLicensePlate(“XY”).count
[/code]

Hope you found this introduction to Protocol Oriented Programming useful. Please use the comment section to add your feedback/suggestion.

References

WWDC 2015 – Protocol Oriented Programming
Mixing and Traits in Swift 2.0
Protocol-Oriented Programming in Swift 2
Introducing Protocol-Oriented Programming in Swift 2

Filed Under: ios, Swift 2 Tagged With: Protocol, Protocol Oriented Programming, Struct

SwiftExpress – Web Application Server in Swift

February 29, 2016 By Ravi Shankar Leave a Comment

Swift Express is a simple yet powerful web application written in Apple’s Swift language. This is an initiative started by Crossload Labs using Play Framework and Express.js

Installation

SwiftExpress GitHub provides a well documented steps for installing the server on Mac OS X and Linux. I tried this on Mac OS X and the whole setup was completed in less 10 minutes and was able quickly run the demo API request.

Features

Feature supported by Swift Express (Note :- re-published from SwiftExpress GitHub repository)

  • ? Linux support with and without Dispatch
  • 100% asynchronous (Future-based API)
  • Flexible and extensible
  • Full MVC support
  • Swift 2.1 and 2.2 compatible
  • Simple routing mechanism
  • Request handlers chaining
  • Typesafe Error Handlers
  • Templeates: Stencil and Mustache
  • Built-in JSON support
  • Easy creation of RESTful APIs
  • Built-in static files serving
  • Multiple contents types built-in support

A Quick Demo

Let us see a quick demo of JSON API Service deployed on SwiftExpress and consumed by iOS App written Swift.

Project Creation

Make sure to install the required libraries before creating the project. Launch terminal window and type the following

[code language=”plain”]swift-express init APIDemo
[/code]

The project creation should kick start the following set of dependancies updates.

[code language=”plain”]*** No Cartfile.resolved found, updating dependencies
*** Fetching Express
*** Fetching Stencil
*** Fetching CEVHTP
*** Fetching PathToRegex
*** Fetching Regex
*** Fetching GRMustache.swift
*** Fetching TidyJSON
*** Fetching BrightFutures
*** Fetching PathKit
*** Fetching ExecutionContext
*** Fetching Result
*** Checking out CEVHTP at "0.1.0"
*** Checking out GRMustache.swift at "bf7d6031d7e0dd862519eaba2b36b2e11a0d25a9"
*** Checking out Result at "1.0.3"
*** Checking out ExecutionContext at "0.3.1"
*** Downloading Regex.framework binary at "v0.5.2: Linux support final"
*** Downloading Express.framework binary at "v0.3.1: OS X binary build"
*** Checking out PathKit at "0.6.1"
*** Downloading TidyJSON.framework binary at "v1.1.0: faster parser"
*** Downloading PathToRegex.framework binary at "v0.2.0: linux support"
*** Checking out Stencil at "0.5.3"
*** Checking out BrightFutures at "0.4.0"
*** xcodebuild output can be found in /var/folders/gs/586wmrks50b9xdpq1309qn9m0000gn/T/carthage-xcodebuild.hzo8CL.log
*** Building scheme "MustacheOSX" in Mustache.xcworkspace
*** Building scheme "PathKit" in PathKit.xcworkspace
*** Building scheme "Result-Mac" in Result.xcodeproj
*** Building scheme "ExecutionContext-OSX" in ExecutionContext.xcodeproj
*** Building scheme "BrightFutures-Mac" in BrightFutures.xcworkspace
*** Building scheme "Stencil" in Stencil.xcodeproj
ld: warning: linking against dylib not safe for use in application extensions: /Users/ravishankar/Downloads/Demo/APIDemo/Carthage/Checkouts/BrightFutures/Carthage/Build/Mac/ExecutionContext.framework/ExecutionContext
Task: "init" done.[/code]

Navigate to APIDemo project folder and launch APIDemo.xcodeproj

[code language=”plain”]cd APIDemo
open APIDemo.xcodeproj[/code]

You should see the following project structure with main.swift file.

Create JSON API Call

Now edit the main.swift file and add app.views.register(JsonView())to enable JSON API service. This can be added below the app.views.register(StencilViewEngine())

Let us create a JSON Service that returns details about Marathon Runs for 2016. We should register a new API route /marathon/ and the response returned by service has been hard code as shown below. The app.get can be added above the app.listen(9999) method call.

[code language=”swift”]app.get("/marathons/") { request in
//compose the response as a simple dictionary
let response = [
[
"name": "Tokyo Marathon",
"date": "28/02/2016"
],
[
"name": "Dong-A Seoul International Marathon",
"date": "20/03/2016"
],
[
"name": "Aalborg Brutal Marathon",
"date": "25/03/2016"
],
[
"name": "Bath Beat Marathon",
"date": "02/04/2016"
],
[
"name": "Freiburg Marathon",
"date": "03/04/2016"
],
[
"name": "Canberra Marathon",
"date": "10/04/2016"
],
[
"name": "NN Rotterdam Marathon",
"date": "10/04/2016"
],
[
"name": "Vienna City Marathon",
"date": "10/04/2016"
],
[
"name": "Haspa Marathon Hamburg",
"date": "17/04/2016"
],
[
"name": "Blackpool Marathon",
"date": "24/04/2016"
]
]
//render disctionary as json (remember the one we’ve registered above?)
return Action.render(JsonView.name, context: response)
}[/code]

Compiling and run the project in Xcode should show “Express was successfully launched on port 9999” in the console message. Accessing the following url should display the JSON Response as shown below.

Now consuming this JSON service from iOS App using NSURLSession class as shown below.

[code language=”swift”]func loadData() {
let url = NSURL(string:"http://localhost:9999/marathons")

let request = NSURLRequest(URL: url!)

let session = NSURLSession.sharedSession().dataTaskWithRequest(request)
{ (data, response, error) -> Void in

if let error = error {
print("Error " + (error.localizedDescription))
return
}

if let data = data {
do {
let results = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) as! NSArray
for item in results {
print(item)
self.details.append(item as! [String : String])
}

dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
} catch (let error as NSError) {
print("JSON error" + error.localizedDescription)
}

} else {
print("No response")
return
}
}
session.resume()
}

[/code]

Since we are running the service using http, make sure to add Allow Arbitrary Loads to “YES” (under App Transport Security Settings) in info.plist file.

Looking forward to the production release of Swift Express !!!

Filed Under: ios, Swift, Swift 2 Tagged With: SwiftExpress, Web Service

What is new in Swift 2.0

October 20, 2015 By Ravi Shankar Leave a Comment

Lots of new feature have been introduced as part of Swift 2.0. The list includes guard, repeat-while, defer, error handling, protocol extensions, print, pattern matching, early exits, UI Testing, UI Stackview etc. Let us see some of these cool features.

guard, try and catch

[code language=”swift”]func printISPDetails() {

let url = NSURL(string: “http://www.telize.com/geoip”)
let request = NSURLRequest(URL: url!)

let session = NSURLSession.sharedSession()

let task = session.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
guard error == nil else {
print(“Error while calling the webservice ” + error!.localizedDescription)
return
}

let status = (response as! NSHTTPURLResponse).statusCode

guard status == 200 else {
print(“Received response status code as \(status)”)
return
}

guard data != nil else {
print(“data not received from webservice”)
return
}
do {
let dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments)
print(dict)
} catch let error as NSError {
print(“Error parsing JSON response ” + error.localizedDescription)
}
}
task.resume()
}
[/code]

The guard statement is used for checking the else part i.e when there is error print the error and exit the function.

[code language=”swift”]guard error != nil else {
print(“Error while calling the webservice ” + error!.localizedDescription)
return
}[/code]

Then we have the try catch statments used for parsing the JSON response. Prior to Swift 2.0, JSONObjectWithData method had an extra argument (NSError) for cpaturing the error. Now in Swit 2.0 this is done in cleaner way by throwing an exception when any errors occur while parsing the JSON response. And you can handle this using do, try , catch block as shown below.

[code language=”swift”] do {
let dict = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments)
print(dict)
} catch let error as NSError {
print(“Error parsing JSON response ” + error.localizedDescription)
}
[/code]

defer

if you coming from Java background then defer is simular to finally statement. You can use when you call a piece of code irrespective of success of failure of opertation. One common example would be closing the file handle in a function does a read write operation to a file.

[code language=”swift”]defer { ..code… }
[/code]

repeat

We all know how do while works, the gets executed for the first time irrespective of codition in the while loop.

[code language=”swift”]var index = 0
do {
print(index)
index++
} while (index < 10)[/code]

In Swift 2.0, the do keyword is replaced by repeat. Makes more sense right!

[code language=”swift”]var index = 0
repeat {
print(index)
index++
} while (index < 10)[/code]

Filed Under: ios, Swift 2 Tagged With: defer, guard, try and catch

Primary Sidebar

TwitterLinkedin

Recent Posts

  • How to block keywords in Jio broadband
  • How to disable opening an app automatically at login in Mac
  • How to set preferred Wifi network on Mac
  • Attribute Unavailable: Estimated section warning before iOS 11.0
  • How to recover Firefox password from Time Machine backup

Pages

  • About
  • Privacy Policy
  • Terms and Conditions

Copyright 2022 © rshankar.com

Terms and Conditions - Privacy Policy