• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • About
  • Portfolio
  • Privacy Policy

Archives for February 2016

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: Swift, Swift 2 Tagged With: SwiftExpress, Web Service

Keyboard Shortcuts in Xcode

February 19, 2016 By Ravi Shankar Leave a Comment

Listed below are the various keyboard shortcuts in Xcode 7. Symbols corresponding to Mac keyboard used are command (⌘), shift (⇧), control (⌃), option/alt (⌥)

Build, Run, Test

Build ⌘ + B
Clean ⌘ + ⇧ + K
Run Tests ⌘ + U
Run ⌘ + R

Debug

Step Over F6
Step Into F7
Step Out F8
Toggle BreakPoint ⌘ + \
Enable or disable BreakPoints ⌘ + Y
Continue ⌃ + ⌘ + Y

Navigator

Show/Hide ⌘ + 0

Project Navigator ⌘ + 1
Symbol Navigator ⌘ + 2
Find Navigator ⌘ + 3
Issue Navigator ⌘ + 4
Test Navigator ⌘ + 5
Debug Navigator ⌘ + 6
Breakpoint Navigator ⌘ + 7
Report Navigator ⌘ + 8

Utility Pane

Show/Hide ⌘ + ⌥ + 0

File Inspector ⌘ + ⌥ + 1
Quick Help Inspector ⌘ + ⌥ + 2
Identity Inspector ⌘ + ⌥ + 3
Attributes Inspector ⌘ + ⌥ + 4
Size Inspector ⌘ + ⌥ + 5
Connection Inspector ⌘ + ⌥ + 6

File Template Library ⌃ + ⌘ + ⌥ + 1
Code Snippet Library ⌃ + ⌘ + ⌥ + 2
Object Library ⌃ + ⌘ + ⌥ + 3
Media Library ⌃ + ⌘ + ⌥ + 4

Find and Replace

Find in Project ⌘ + ⇧ + F
Find / Replace in Project ⌥ + ⌘ + ⇧ + F

Find ⌘ + F
Find / Replace ⌥ + ⌘ + F
FInd Next ⌘ + G
Find Previous ⌘ + ⇧ + G

Editor

Quickly open file ⌘ + ⇧ + O
Open definition ⌃ + ⌘ + J
Comment / Uncomment ⌘ + /
Assitant Editor ⌘ + ⌥ + ⏎
Hide Assitant Editor ⌘ + ⏎
Related Items menu ⌃ + 1
Indent Selection to Right ⌘ + ]
Indent Selection to Left ⌘ + [
Re Indent ⌃ + I
Reveals Current file in Navigator ⌘ + ⇧ + J
Move focus to editor ⌘ + J

Interface Builder

Selected View Move Up ↑
Selected View Move Down ↓

Update frame ⌥ + ⌘ + =
Update Constraint ⇧ + ⌘ + =
Open all views ⇧ + ⌃ + Click

Documentation

Documentation Popup ⌥ + Click

Filed Under: Uncategorized

How to programmatically add AutoLayout constraints?

February 18, 2016 By Ravi Shankar 2 Comments

AutoLayout solves the mystery when designing app for more than one screen size and for both Portrait and Landscape orientation. This is done by adding constraints to the views using various Auto Layout options available as part of Interface Builder. As an iOS developer, you can also add these constraints programmatically using NSLayoutConstraints or Visual Format Languages. In this tutorial we will see how to use NSLayoutConstraints for adding constraints to the views.

Screen Design For this Demo

For this demo, we will design something similar to flag of England by adding all the views and constraints programmatically. Funza Academy have published a video tutorial on how to design this screen using Interface Buidler, please check that out.

 

Overview of Steps

The following will be done to create the UI programmatically.

  1. Change the background colour of View to Red
  2. Add four rectangular views of equal widths on top left, top right, bottom left and bottom right of the parent view. The background colour for all these views will be set to red and Super View to red
  3. Pin the four rectangular views to the corresponding corner by adding constraints.
  4. Add constraints to the views to leave constant gap between each views (white background). This would ensure red line is shown in between these views.
  5. Disable AutoResizingMasks for teh four sub views.

Project Setup

Create a new Xcode project by selecting Single View Application for the project template. Also choose the language and Swift and iPhone for Devices.

Create Views

Navigate to ViewController.swift file and add the following code snippet after the class declaration and above the viewDidLoad() function.

[code language=”swift”]private let SCREEN_SIZE = UIScreen.mainScreen().bounds
private let GAP_BETWEEN_VIEWS:CGFloat = 0.08

// Create four Subviews

var topLeftView = UIView()
var topRightView = UIView()
var bottomLeftView = UIView()
var bottomRightView = UIView()[/code]

The above set of code creates two constants which stores the screen size and specifies the gap between the views. Then we have created four variables that holds the instance of four views.

Add the following addViews functions below the viewDidLoad method

[code language=”swift”]
func addViews() {
let heightOfSubView = SCREEN_SIZE.height / 2 – SCREEN_SIZE.height * GAP_BETWEEN_VIEWS/2
let widthOfSubView = SCREEN_SIZE.width / 2 – SCREEN_SIZE.height * GAP_BETWEEN_VIEWS/2

// Calculate the height and size of each views
topLeftView = UIView(frame: CGRect(x: 0, y: 0, width: widthOfSubView, height: heightOfSubView))
topRightView = UIView(frame: CGRect(x: widthOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), y: 0, width: widthOfSubView, height: heightOfSubView))
bottomLeftView = UIView(frame: CGRect(x: 0, y: heightOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), width: widthOfSubView, height: heightOfSubView))
bottomRightView = UIView(frame: CGRect(x: widthOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), y: heightOfSubView + (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS), width: widthOfSubView, height: heightOfSubView))

topLeftView.backgroundColor = UIColor.whiteColor()
topRightView.backgroundColor = UIColor.whiteColor()
bottomLeftView.backgroundColor = UIColor.whiteColor()
bottomRightView.backgroundColor = UIColor.whiteColor()

view.addSubview(topLeftView)
view.addSubview(topRightView)
view.addSubview(bottomLeftView)
view.addSubview(bottomRightView)
}
[/code]

The addViews function, calculates the height and width of each subview (rectangular view with white background). Then the four views are created with positioning them in the corresponding corners i.e topLeft, topRight, bottomLeft and bottomRight. The background colour for these views are set White then they added to parent view using addSubView method.

Now call this addViews function inside viewDidLoad method. Also make sure to set the background colour of parent view to red.

[code language=”swift”]
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.redColor()
addViews()
}
[/code]

Compiling and running this app on iPhone 6 simulator, the portrait mode should look as shown below

And in Landscape mode the views are randomly placed. Let us now fix this by adding the required constraints for all the veiws.

Add Constraints

In order to pin the four subviews, we need to add Leading, Traling, Top and Bottom constraints for the views based on their position. For example the top left view needs a leading and top constraint to the superview. The below screenshot should give a better understanding of constraints required for each view. And we will be adding these constraints using NSLayoutConstraint class

Pin the views to the side

Add the following code snippet that which creates Leading and Top constraint for TopLeft view.

[code language=”swift”]func addtopLeftViewConstraints() {
let topLeftViewLeadingConstraint = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)

let topLeftViewTopConstraint = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topLeftViewLeadingConstraint, topLeftViewTopConstraint])
}
[/code]

First we create a leading constraint to the topLeft view and super view. Then a top constraint is added for topLeft view to the SuperView. Constant refers to the gap between the views using attribute we specify the Leading or Top attributes. Since we do not need any gap between corners the constant value is set to 0. Finally we add these constraints for the view by using the activateConstraints function in NSLayoutConstraint class.

Now let us repeat the above steps topRight. bottomLeft and bottomLeft Views.

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

let topRightViewTrailingConstraint = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)

let topRightViewTopConstraint = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewTrailingConstraint, topRightViewTopConstraint])
}

func addBottomLeftViewConstraints() {

let bottomLeftViewLeadingConstraint = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)

let bottomLeftViewBottomConstraint = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([bottomLeftViewLeadingConstraint, bottomLeftViewBottomConstraint])

}

func addBottomRightViewConstraints() {

let bottomRightViewTrailingConstraint = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)

let bottomRightViewBottomConstraint = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal
, toItem: view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([bottomRightViewTrailingConstraint, bottomRightViewBottomConstraint])
}[/code]

Leave space between views

We need leave constant space in the middle between these views. This can be achieved by adding constriants between the top/bottom views and left/right views. So basically we need to add two vertical spacing and two horizontal spacing constraints.

The below code snippet adds the required spacing constraings between views by specifying a constant value. Then activate these constraints by calling NSLayoutConstraint.activateConstraint.

[code language=”swift”] func addTopBottomConstraints() {
let verticalSpacing1 = NSLayoutConstraint(item: bottomLeftView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topLeftView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

let verticalSpacing2 = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

NSLayoutConstraint.activateConstraints([verticalSpacing1, verticalSpacing2])
}

func addLeftRightConstraints() {
let horizontalSpacing1 = NSLayoutConstraint(item: topRightView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: topLeftView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

let horizontalSpacing2 = NSLayoutConstraint(item: bottomRightView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: (SCREEN_SIZE.height * GAP_BETWEEN_VIEWS))

NSLayoutConstraint.activateConstraints([horizontalSpacing1, horizontalSpacing2])
}
[/code]

Add Equal Width and Equal Height

Now add Equal Width and Equal Height constraints for topRight, bottomLeft and bottomRight views based on topLeft View. The code snippet for EqualWidth and EqualHeight is given below. The first function adds equal width constaints for all the three views based on TopLeft view. Similarly the second function adds equal height constraints based on the TopLeft view.

[code language=”swift”]
func addEqualWidthConstraints() {
let topRightViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

let bottomLeftViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

let bottomRightViewWidth = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: bottomRightView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewWidth, bottomLeftViewWidth,bottomRightViewWidth ])
}

func addEqualHeightConstraints() {
let topRightViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: topRightView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

let bottomLeftViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: bottomLeftView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

let bottomRightViewHeight = NSLayoutConstraint(item: topLeftView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: bottomRightView, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)

NSLayoutConstraint.activateConstraints([topRightViewHeight, bottomLeftViewHeight,bottomRightViewHeight ])
}[/code]

Disable AutoResizingMasks

Finally we need to disable the auto resizing masks for all the views to prevent constraints getting automatically based on the autoResizingMask property. The autoResizingMask property is set to true when the views are added programmtically added so we need make sure that this property for all these views are set to false.

[code language=”swift”]func disableAutoResizingMasks() {
topLeftView.translatesAutoresizingMaskIntoConstraints = false
topRightView.translatesAutoresizingMaskIntoConstraints = false
bottomLeftView.translatesAutoresizingMaskIntoConstraints = false
bottomRightView.translatesAutoresizingMaskIntoConstraints = false
}[/code]

Just to make code little organized, we can create a new function that calls these constraints functions.

[code language=”swift”]func addConstraints() {
addtopLeftViewConstraints()
addTopRightViewConstraints()
addBottomLeftViewConstraints()
addBottomRightViewConstraints()
addTopBottomConstraints()
addLeftRightConstraints()
addEqualWidthConstraints()
addEqualHeightConstraints()
disableAutoResizingMasks()
}
[/code]

Then call the addConstraints function in viewDidLoad method

[code language=”swift”]override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = UIColor.redColor()

addViews()
addConstraints()
}[/code]

If you need any assistance in Auto Layout, check out our new iOS 9 Auto Layout Tutorials.

Download the source code from GitHub

Filed Under: Auto Layout Tagged With: NSLayoutConstraint, Swift

A trick to flip a column upside down in Excel

February 17, 2016 By Ravi Shankar Leave a Comment

Excel users can sort a column using the Sort feature available as part of Sort & Filter menu. But what if you want to flip a column upside down. Let us see this with an example column having some text values as shown below.

We will not be able to apply sort feature directly on this column to flip the data instead we can add a dummy column and use that for sorting the text values.

Step 1: Insert a new column before the existing column.
Step 2: Now use Auto Fill feature to fill the temp with numbers as shown below

Step 3: Now you can use the Sort feature on column1 and make sure to sort by descending order. Also include the column2 in Sort sleection list.

Step 4: Once the columns are sorted, delete the temp column with numbers.

Filed Under: Excel, Excel 2007, Excel 2010, Excel 2013, MS Office

Primary Sidebar

Recent Posts

  • We have blocked all requests from this device – Firebase Phone Authentication
  • iPhone is not available error message in Xcode
  • Clear CocoaPods cache, re-download and reinstall all pods
  • PDFKit – View, Annotate PDF file in Swift
  • Tab Bar Controller with WebView

Archives

  • September 2020
  • April 2020
  • December 2019
  • November 2019
  • October 2019
  • February 2019
  • October 2017
  • June 2017
  • May 2017
  • March 2017
  • September 2016
  • March 2016
  • February 2016
  • January 2016
  • December 2015
  • November 2015
  • October 2015
  • September 2015
  • August 2015
  • July 2015
  • June 2015
  • May 2015
  • April 2015
  • March 2015
  • February 2015
  • January 2015
  • December 2014
  • November 2014
  • October 2014
  • September 2014
  • August 2014
  • July 2014
  • June 2014
  • April 2014
  • March 2014
  • February 2014
  • January 2014
  • December 2013
  • October 2013
  • August 2013
  • July 2013
  • June 2013
  • April 2013
  • March 2013
  • February 2013
  • January 2013
  • November 2012
  • August 2012
  • July 2012
  • June 2012
  • May 2012
  • March 2012
  • February 2012
  • January 2012
  • December 2011
  • October 2011
  • September 2011
  • August 2011
  • July 2011
  • June 2011
  • April 2011
  • March 2011
  • January 2011
  • September 2010
  • August 2010
  • July 2010
  • June 2010
  • July 2009
  • March 2008

Copyright 2020 © rshankar.com