• Skip to main content
  • Skip to primary sidebar

Ravi Shankar

Tweaking Apps

  • About
  • Portfolio
  • Privacy Policy

Swift

Class and Struct in Swift

May 10, 2015 By Ravi Shankar 3 Comments

Download the playground file from github (Classes and Struct)

Class

A class is a blue print for a real-word entity such Player, Person etc. and it is used for creating objects. Class can have properties to store values and methods to add behaviour. Let us see this with an example class called Rectangle which has some properties and two methods for calculating area and for drawing a rectangle.

[code language=”swift”]class Rectangle {

var name:String = ””
var length:Double = 0
var breadth:Double = 0

func area() -> Double {
return length * breadth
}

func draw() -> String {
return “Draw rectangle with area \(area()) “
}
}

let rect = Rectangle()

rect.length = 20
rect.breadth = 10
rect.draw()
[/code]

 

In the above example, we have a class named Rectangle, with name, length and breadth as properties, area and draw are functions. rect is a instance variable or object of Rectangle class. On setting the length and breadth and calling draw function should provide the following output in Playground.

201505101309.jpg

Similarly the below code create a Square class

[code language=”swift”]class Square {

var name:String = ””
var length:Double = 0

func area() -> Double {
return length * length
}

func draw() -> String {
return “Draw a square with area \(area()) “
}
}

let squr = Square()
squr.length = 20
squr.draw()
[/code]

 

Now instead of repeating property and functions in each classes let us use class inheritance to simplify these classes.

Class Inheritance

Let us create a parent class called Shape and its properties and functions will be inherited by Sub Classes Rectangle and Square.

Parent Class – Shape

[code language=”swift”]class Shape {
var name: String = ””

func area() -> Double {
return 0
}

func draw() -> String {
return “Draw a \(name) with area \(area()) “
}
}
[/code]

 

Sub Class – Square

[code language=”swift”]class Square:Shape {

var length: Double = 0
override func area() -> Double {
return length * length
}
}

let squr = Square()
squr.name = “My Square”
squr.length = 5
squr.draw()
[/code]

 

Sub Class – Rectangle

[code language=”swift”]class Rectangle:Shape {
var length: Double = 0
var breadth: Double = 0

override func area() -> Double {
return length * breadth
}
}

let rect = Rectangle()
rect.name = “My Rectangle”
rect.length = 5
rect.breadth = 10
rect.draw()
[/code]

 

Parent class Shape has been created with name property and functions area and draw. The child class Square and Rectangle will inherit these property and methods. Apart from the parent class property, Square can have its own property length and Rectangle has length and breadth. The parent class area function has been overridden by Square and Rectangle class to calculate corresponding areas. Now if you want add one more Shape such as Triangle, Circle etc the new class has to inherit Parent class (Shape) and add its own property and methods (or override methods).

Initialisers

Initialisers in Class and Struct are used for setting the default values for properties and for doing some initial setup. Here is a typical example of initialiser in a Class where the name property is initialised at the time of creating an instance.

[code language=”swift”]class Shape {

var name: String
init(name: String) {
self.name = name
}

func area() -> Double {
return 0
}

func draw() -> String {
return “Draw a \(name) with area \(area()) “
}
}

class Square: Shape {
var length: Double = 0

init() {
super.init(name: “MySquare”)
}

override func area() -> Double {
return length * length
}

override func draw() -> String {
return “Draw a \(name) with area \(area()) “
}
}

let squr = Square()
squr.length = 10
squr.draw()
[/code]

 

The sub class Square initialises the name property in init function by calling super.init and after creating the Square instance you need to pass value for the length property.

Designated and Convenience Initialisers

Initialiser which initialises all the properties in a class is known as designated initialiser. A convenience initialiser will initialise only selected properties and in turn will call the designated initialiser in init function. Listed below is a Square class with designated initialiser and convenience initialiser

[code language=”swift”]class Shape {
var name: String
init(name: String) {
self.name = name
}

func area() -> Double {
return 0
}

func draw() -> String {
return “Draw a \(name) with area \(area()) “
}
}

class Square: Shape {
var length: Double

// Designated Initializer
init(length:Double, name:String) {
self.length = length
super.init(name: name)
}

// Convenience Initializer
convenience init(length: Double) {
self.init(length:length, name:“MySquare”)
}

override func area() -> Double {
return length * length
}

override func draw() -> String {
return “Draw a \(name) with area \(area()) “
}
}

let squr = Square(length: 10,name: “MySquare”)
squr.draw()

let squrNew = Square(length: 20)
squrNew.draw()[/code]

Computed Property

A property in swift can be used for performing operation at the time of assigning value. Here is an example, where the length of Square is computed based on assigned area.

[code language=”swift”]class Sqaure {
var length: Double = 0
var area: Double {
get {
return length * length
}

set (newArea) {
self.length = sqrt(newArea)
}
}
}

let square = Sqaure()
square.area = 4 // set call
square.length = 6
square.area // get call[/code]

lazy Property

Swift also provides lazy property whose value is assigned when the user access the property.

[code language=”swift”]class Person {
var name: String
init (name: String) {
self.name = name
}

lazy var message: String = self.getMessage()

func getMessage() -> String {
return “Hello \(name)”
}
}

let person = Person(name: “Jason”)
person.message[/code]

in the above code example, the value for message property is not set at the initialisation and will be set only when call the message property in person object. Some typical where you could due lazy property is when retrieving values from performance intensify operation such as Network or Read/Write.

Property Observers

Swift provides two property observers, willSet and didSet. These methods gets triggered when a value is about to be set for a property or after setting the property.

[code language=”swift”]class Square {
var length: Double = 0 {
willSet(newLength) {
println("Setting length \(self.length) to new length \(newLength)")
}

didSet {
println(“Length is modified – do some action here”)
}
}

var area: Double {
get {
return length * length
}

set (newArea) {
self.length = sqrt(newArea)
}
}
}

let square = Square()
square.length = -6
square.area
[/code]

 

In the above example, Square class length property has a willSet and didSet observers.

Struct

Struct and Class can both have properties, methods, protocols, extensions and initialisers. You can use struct to hold simple values and when you want to pass around those across your program. A typical example would be using Struct to hold values from a web service call. Listed below is a web service call that we had seen earlier in Xcode and Playground overview. In the below code example you should find a GeoDetails struct for storing the values returned from geoip web service.

[code language=”swift”]struct GeoDetails {
var country: String
var ip: String
var isp: String
var latitude: Double
var longitude: Double
var timeZone: String

init(country: String, ip: String, isp: String, latitude:Double, longitude:Double, timeZone:String) {
self.country = country
self.ip = ip
self.isp = isp
self.latitude = latitude
self.longitude = longitude
self.timeZone = timeZone
}

func description() -> String {
return “Country ” + self.country + “, ip ” + self.ip + “, isp ” + self.isp + “, latitude \(self.latitude), longitude \(self.longitude) “
}
}

var geoDetails: GeoDetails?
XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true)

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

NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in
if error == nil {
var error:NSError?
if let result = data {
if let dict = NSJSONSerialization.JSONObjectWithData(result, options: NSJSONReadingOptions.AllowFragments, error: &error) as? NSDictionary {
geoDetails = GeoDetails(country: dict[“country”] as! String, ip: dict[“ip”] as! String, isp: dict[“isp”] as! String, latitude: dict[“latitude”] as! Double, longitude: dict[“longitude”] as! Double, timeZone: dict[“timezone”] as! String)
println(geoDetails?.description())
} else {
println("Error")
}
}[/code]

Download the playground file from github (Classes and Struct)

Filed Under: Apple, Programming Tagged With: Apple, Classes, Structures, Swift

Swift – Beginners Tutorial

May 8, 2015 By Ravi Shankar Leave a Comment

Swift is the latest programming language released by Apple for developing OS X and iOS apps.

  • Best of C and Objective-C
  • Adopts safe programming patterns and modern features
  • Supports Playground, a tool for seeing the result immediately.
  • Provides access to Cocoa libraries and can work in conjunction with Objective-C
  • Combines Procedural and Object-Oriented programming.
  • No need to use semicolon at the end of statement. Use it only when you have more than one statement in single line.
  • Swift uses var and let. only mutable variable needs var.
  • Swift uses type inference.
  • Supports unicode characters. You can use any character as variable.
  • Prefer usage of constant (let) for immutable than using var.
  • Optional variables can contain value or nil. – var givenName : String? = “Ravi”
  • Swift’s Switch supports all kinds of datatype and operations and does not need a break statement after each case statement.
  • No need to enclose your expression in brackets with if statements
  • Swift function supports default value for the parameter and variable parameter.
  • Closures are like blocks in Objective-C ( ) -> ( )
  • No need to specify header file in Swift
  • No need to specify base class and there is no universal base class
  • No difference between instance variable and properties
  • Tuples – Grouping of multiple values.
  • Nested multiline comments are allowed.
  • Use typealias to provide different name to an existing type.
  • Swift nil represents absence of value and objective – C nil represents pointer to a non-existent object.
  • Implicitly unwrapped optional let pincode : String! = “E151EH”
  • Provides Assertion to end code execution where certain criteria is not met.
  • Swift’s String is value type and not passed by reference.
  • Supports Optional Binding and Optional Chaining

Variables and Constants

[code language=”swift”]
// Variables and Constants

var myStr = "Swift"
var myValue = 23.1 //(Implicit variable declaration or type inference)
var myDoubleValue: Double = 23 //(Explicit variable declaration)

// let

let myAge = 38
let message = "My age is " + String(myAge) //(Converting value to a String)
let newMessage = "My age is \(myAge)" //(Converting value to a String using backslash or interpolation)

[/code]

Data types in Swift

  • String
  • Int (Range -2,147,483,648 to 2,147,483,648)
  • Double (15 digit precision)
  • Float (6 digit precision)
  • Bool

Fun with String

[code language=”swift”]// String
var movie:String = "Independence Day "
count(movie) // count of string

// Use NSString to format a double or float value
var range = NSString(format: "%.2f", 24.5)

// Concatenate String values
movie += String(range)[/code]

 

Collection Types

Array

[code language=”swift”]// Declarations
// var fruits = ["Orange", "Apple", "Grapes"] – Short declartion
// var fruits:Array = ["Orange", "Apple", "Grapes"] – Long declaration
// var fruits:[String] = [] – Assign empty array

var fruits:[String] = ["Orange", "Apple", "Grapes"] // short declaration with type.

// insert item at index
fruits.insert("Mangoes", atIndex: 2)

// append item to the last
fruits.append("Pine Apple")

// count of array
fruits.count

// remove item
fruits.removeAtIndex(1)

// sort array elements
fruits.sort { (a, b) -> Bool in
a < b
}

// retrieve index using find
find(fruits, "Mangoes")
[/code]

Dictionary

[code language=”swift”]// Dicionary

// Declaration

// var employees = [1:"John",2:"Peter",3:"David"] // Short form

// var employees:Dictionary = [1:"John",2:"Peter",3:"David"] // Long form

// var employees:[Int:String] = Dictionary() // Empty dictionary

var employees:[Int:String] = [1:"John",2:"Peter",3:"David"] //Short form with type

// Add new item to dictionary

employees[4] = "Bob"

// Remove an item using key

employees.removeValueForKey(3)
[/code]

Assignment Operator

  • a = b
  • let (a,b) = (2,3) – supports tuple.
  • Does not return value.

Arithmetic Operators

  • Addition (+), Subtraction (-), Multiplication (*), Division (/)
  • + can be used for string concatenation.
  • % – Returns remainder for both +ve and -ve numbers. Also returns remainder for floating point numbers.
  • Increment and Decrement operators, ++i (i = i + 1), —i (i = i – 1).
  • Supports i++ and i— (increments or decrements after returning the value).
  • Unary Minus and Unary Plus

Compound AssignmentOperator

  • x += 2 is same as x = x + 2.

ComparisonOperators

  • x == y
  • x != y
  • x > y
  • x < y
  • x >= y
  • x <= y
  • === and !== used for testing object references.

Ternary Conditional Operator

  • a = flag ? 10 : 20 (if flag is true then a will updated to 10 and 20 incase it is false).

RangeOperators

  • Closed Range – e.g.:- 1…10, has three dots and includes values from 1 to 10.
  • Half Closed – e.g.:- 1..10, has two dots and includes values from 1 to 9

LogicalOperators

  • NOT ( !x )
  • AND ( x && y )
  • OR ( x || y )

Control Flow

[code language=”swift”]// Control flow

// if else
if fruits[0] == "Grapes" {
println("for breakfast")
} else if fruits[0] == "Apple" {
println("for lunch")
} else {
println("Nothing")
}

// for statements
// exclusive range

for index in 0..<h3><u>Comments</u></h3>[code language="swift"] Single line comments // examples
Multiline comments /* example1
example2 */

[/code]

Function

[code language=”swift”]func sum(number1:Int, number2: Int) -&gt; (Int) {
return number1 + number2
}[/code]

The above function is an example of multiple input parameters. It does the addition of two numbers where number1 and number are arguments of type Int and it returns a value of type int. And a function without parameter looks like this.

[code language=”swift”]
func sum() -&gt; (Int) {
return 10 + 5
}[/code]

The above function is an example of multiple input parameters. It does the addition of two numbers. number1 and number are arguments of type Int and it returns a value of type int. And a function without parameter looks like this. Swift function can also have multiple return values.


Define external parameter name

[code language=”swift”]func sum(addNumber1 number1:Int, withNumber2 number2: Int) -&gt; (Int) {
return number1 + number2
}

println(sum(addNumber1: 10, withNumber2: 20))
[/code]

 

addNumber1 and withNumber are external parameter names for two parameters. And you use # to tell local and external parameter name are same.

[code language=”swift”]
func sum(#number1:Int, #withNumber2: Int) -&gt; (Int) {
return number1 + withNumber2
}
println(sum(number1: 10, withNumber2: 20))[/code]

Function with default parameter value

[code language=”swift”]func sum(number1:Int, withNumber2: Int = 20) -&gt; (Int) {
return number1 + withNumber2
}
println(sum(10))[/code]

The above function has default value for the second parameter.

Variadic Parameters

 

A function with variadic parameters can accept zero or more values. Maximum of one parameter is allowed in a function and it is always last in the list.

[code language=”swift”]
// Variadic parameters
func totalSum(numbers:Int…) -&gt; Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
totalSum(1,2,3,4,5)[/code]

Variable and inout parameters

Variable parameters in a function are indicated by var keyword and the scope is available only within the function. If you want to access the modified variable value outside the function then you specify them as inout parameter. And prefix with & while passing the parameter in the function call.

[code language=”swift”]
// inout parameters
var employee = "Ravi"

func greetings(inout employee:String) {
employee += "!"
}
println(greetings(&amp;employee))
println(&amp;employee)[/code]

Filed Under: Apple, ios, Mac Tagged With: Apple, Quick Reference, Swift

Optional binding and Optional Chaining

May 7, 2015 By Ravi Shankar 6 Comments

Swift has a feature that lets users to assign optional value to a variable or a constant. Optional variable or constant can contain a value or a nil value. Let us take the following example which tries to find a given string in a array of string.

Optional Binding

[code language=”swift”]var fruits = ["Apple","Orange","Grape","Mango"]
let searchIndex = find(fruits, "Apple”)[/code]

The searchIndex would return value if the fruit exists or nil value if it doesn’t exist.

[code language=”swift”]println("Fruit index is \(searchIndex)”)
[/code]

 

The proper way to handle this by using Optional binding method.

[code language=”swift”]if let searchIndex = searchIndex {
println("Fruit index is \(searchIndex)")
} else {
println("Not available")
}[/code]

This would ensure only when searchIndex has a value the println with searchIndex gets executed.

Optional Chaining

Optional chaining is the way by which we try to retrieve a values from a chain of optional values. Let us take the following example classes.

[code language=”swift”]class School {
var director:Person?
}

class Person {
var name: String = ""
init(name: String) {
self.name = name
}
}
[/code]

 

[code language=”swift”]
var school = School()
var person = Person(name: "Jason")
school.director = person
school.director?.name
[/code]

The director property in School class is optional, when you try to access subsequent values from director property becomes optional (? mark after director when accessing name property). You can handle these optionals as shown below.

[code language=”swift”]
if let name = school.director?.name {
println("Director name is \(name)")
} else {
println("Director yet to be assigned")
}[/code]

Filed Under: Apple, ios Tagged With: Apple, Optional bindings, Optional chaining, Swift

payworks SDK integration in Swift

March 26, 2015 By Ravi Shankar Leave a Comment

payworks mPOS helps app developers to integrate their App with card reader. In this tutorial, we will see a sample app that integrates payworks mPOS using Swift.

Download the source code from github

Select New Project and choose Single View Application from the template.

201503260807.jpg

In the Project Options window, provide a product name and make sure to select Language as Swift. Click Next and Save the project.

201503260812.jpg

In the Project Navigator, select Main.storyboard and unmark check box “Use Size Classes” in the File Inspector. Then click Disable Size Classes button as this app is only designed for iPhone

201503260825.jpg

UI Design

Design the user interface as shown below.

  • Label to shown caption as Amount
  • TextField for entering the amount
  • Button to Charge Amount.
  • Label to display the status message.

201503260840.jpg

Just to reflect the purpose of this little app, let us rename the ViewController.Swift to ChargeViewController.swift. Make the corresponding changes to Class name as well in Identity Inspector.

Integrate mPOS SDK

We are going to add mPOS SDK to this project using CocoaPods by following the instructions here.

Close your Xcode project, launch Terminal window and and navigate to project folder.

201503260927.jpg

Create a new Podfile with the following statements

201503260929.jpg

Doing a pod install should download the mPOS SDK’s to your project folder.

201503260936.jpg

Now navigate to your project folder and open the file with extension as .xcworkspace. The Pods folder in the project navigator should contain the mPOS framework.

201503260956.jpg

Objective-C Bridging

We need to create a bridge file to call the objective-c related framework files in our Swift app. The easiest way to do this is to create new Objective-C file in your project.

Right click on your project folder, select New File.

201503260959.jpg

In the Choose a template screen, select Objective-C and click Next.

201503261005.jpg

Provide a name for the Objective-C file and save the file.

201503261007.jpg

Now you will prompted whether you would like to configure an Objective-C bridging header. Click Yes to create the bridging header file.

201503261007.jpg

As the header file is created, we do not need the temp objective-c file, you can delete this file.

201503261021.jpg

Navigate to Bridging-Header file in Project navigator and the following lines.

@import Foundation;

#import

Now you can make sure every thing works fine by doing a build. Also make sure to add the additional steps as mentioned in the instruction page for Miura Readers. Navigate to info.plist and add supported external accessory protocols and Required background modes keys.
201503261032.jpg
mPOS integration
Create two IBOutlets, one for TextField and another for Message Label.

  @IBOutlet weak var amountTxtField: UITextField!

@IBOutlet weak var messageLabel: UILabel!

  

Use the connection inspector to connect the IBOutlets with the controls.

201503261037.jpg

In order to connect with mPOS SDK, you need to register and get the merchant credentials, You can do this by registering here. After receiving the credentials create two constants to hold the identifier and secret key.

  let MERCHANT_IDENTIFIER = “YOUR_MERCHANT_IDENTIFIER”

let MERCHANT_SECRET_KEY = “YOUR_SECRET_KEY”

201503261049.jpg
Now add the following IBAction method to ChangeViewController.swift and connect the IBAction with the button.

  @IBAction func chargeCard(sender: UIButton) {

  

let amount:NSDecimalNumber = NSDecimalNumber(string: self.amountTxtField.text)

  

let transactionProvider:MPTransactionProvider = MPMpos .transactionProviderForMode( MPProviderMode.MOCK, merchantIdentifier: MERCHANT_IDENTIFIER, merchantSecretKey: MERCHANT_SECRET_KEY)

  

let template: MPTransactionTemplate = transactionProvider.chargeTransactionTemplateWithAmount(amount, currency: MPCurrency.EUR, subject: “subject”, customIdentifier: “customIdentifier”)

  

let paymentProcess:MPPaymentProcess = transactionProvider.startPaymentWithTemplate(template, usingAccessory: MPAccessoryFamily.Mock, registered: { (let paymentProcess:MPPaymentProcess!, let transaction:MPTransaction!) -> Void in

  

}, statusChanged: { (let paymentProcess:MPPaymentProcess!, let transaction:MPTransaction!, let paymentProcessDetails:MPPaymentProcessDetails!) -> Void in

  

self.messageLabel.text = self.formatMessage(paymentProcessDetails.information)

  

}, actionRequired: { (let paymentProcess:MPPaymentProcess!, let transaction:MPTransaction!, let transactionAction:MPTransactionAction, let transactionActionSupport:MPTransactionActionSupport!) -> Void in

  

}) {(let paymentProcess:MPPaymentProcess!, let transaction:MPTransaction!, let paymentProcessDetails:MPPaymentProcessDetails!) -> Void in

  

self.messageLabel.text = self.formatMessage(paymentProcessDetails.information)

}

}

  

func formatMessage(information:AnyObject) -> String {

let temp = (information[0] as NSString) + “\n”

return temp + (information[1] as NSString)

}

Since I don’t have a real reader to try this demo, I have used Mock mode for the transaction provider and payment process
  let transactionProvider:MPTransactionProvider = MPMpos .transactionProviderForMode( MPProviderMode.MOCK, merchantIdentifier: MERCHANT_IDENTIFIER, merchantSecretKey: MERCHANT_SECRET_KEY)

  let paymentProcess:MPPaymentProcess = transactionProvider.startPaymentWithTemplate(template, usingAccessory: MPAccessoryFamily.Mock, registered:

Now you are good to try this demo by entering an amount and tap the Pay button. The trisection status will be displayed in the message label.

201503261058.jpg
You can also test your solution by entering different amount as mentioned in the test page.
201503261101.jpg
Download the source code from github

Filed Under: Apple, iPhone, Mac, Programming Tagged With: Apple, integration, payowrks, Swift

Debugging Swift App in Xcode

February 17, 2015 By Ravi Shankar 1 Comment

Any beginner iOS developer should be aware of the NSLog statement. This is quite frequently used to debug Objective-C programs. In Swift you can use println or print statement instead of NSLog to write the debug information to the console log.

[code language=”swift”]var primeFlag:Bool = true
println("input number is \(number)")
if ((number == 2) || (number == 3)) {
return primeFlag
}
[/code]

 

This will write the following message in the console log.

input number is 5

But debugging a large app using println statement will be a time consuming process, instead you can use Xcode built-in features for debugging.

Breakpoint

 

Xcode users can place breakpoint at a specific statement and when the program execution reaches that line it pauses the execution. The breakpoint allows users to examine the value of variables at that specific context.

201502160926.jpg

Like any other IDE, Xcode provides option to Step Into, Step Out, Step Over and Continue option.

201502160929.jpg

Exception Breakpoint

When your app crashes and you want the app the stop at the line of statement that causes the crash then you can use Exception breakpoint. Click Debug menu and select Create Exception Breakpoint from the menu list.

201502161005.jpg

Conditional breakpoint

If you want to pause the execution using a breakpoint when a condition is met then you can use conditional breakpoint.

201502162238.jpg

Right click a breakpoint and select Edit BreakPoint from the list. Then add the add the condition for the breakpoint. In the below screenshot, when index reaches 251 the breakpoint will be activated.

201502170549.jpg

Symbolic breakpoint

Symbolic breakpoint pauses the program execution when it reaches the specified method. For example you want to pause the program execution in all the viewDidLoad methods then you can specify that using Symbolic breakpoint.

Debug menu -> Breakpoints -> Create Symbolic Breakpoint

201502170555.jpg

Enter the method name in symbol field and to target only specific module instead of all viewDidLoad methods you can enter the module name as well.

201502170820.jpg

Watch Point

When you want to pause the app execution whenever the value of a variable changes then you can use watch point. You can add a watch point by selecting variable and picking Watch option from the context menu.

201502170829.jpg

Breakpoint navigator

Xcode Breakpoint navigator will show the list of breakpoints that are currently active in your project.

201502170836.jpg

And you can remove all and selected breakpoints by right clicking on the Breakpoint navigator and selecting Delete Breakpoints option.

201502170838.jpg

Enable sound

Another useful feature which is available as part of Xcode debugging tool is to play sound when a breakpoint condition is met. This is quite useful when you have Xcode debugging in the background and want to let you know when the condition is met by playing the sound.

201502170845.jpg

To specify the condition, click on the Action drop down and select Sound from the list. Then add the notification sound that needs to played when the condition is met.

201502170846.jpg

Filed Under: Apple, ios, Programming, Xcode Tagged With: Apple, debugging, Swift, Xcode

Test Driven Development in Swift

February 9, 2015 By Ravi Shankar Leave a Comment

Here is a beginner tutorial on TDD in Swift by writing a program that checks for a prime number. Let us start by creating a new project, selecting template as Single View Application. Though we won’t be adding anything to the storyboard as we will focus only on the business logic.

201502082101.jpg

201502082103.jpg

After creating the project, the project navigator should have the following structure.

201502082104.jpg

from wikipedia

A prime number is a natural number greater than 1 that no positive divisors other than 1 and itself. – 2,3,5,7,11,13 ….

So now that we know the first prime number is 2, let us add a unit test that checks if number 2 is a prime number. We are going to have a new class called Util that will have the required function to check if a number is prime number. Before creating a Util class, create unit test class called TestsForUtil.swift.

201502082115.jpg

Select the template as Test Case Class and go with the default settings. Now you should see the newly added class as part of the project navigator under CheckForPrimeTests.

201502082117.jpg

As we don’t need CheckForPrimeTests.Swift, we can delete the file. And on opening TestsForSwift.swift, you should notice the following default test methods. setup(), tearDown(), testExampe(), testPerformanceExample(). In this demo, we are not going to use any of these methods and so you can remove them as well.

Let us add our first unit test that checks if number 2 is prime number. Add the following method,

func testTwoIsPrime() {

let number:Int = 2;

XCTAssertTrue(Util().isPrime(number), “2 is a prime number”);

}

You should see use of Unresolved identifier “Util as we are yet to add the class.

In TDD we write the tests first and then add the required functionality. Test Driven Development will ensure that you add only required code to pass your tests.

What this test function does is, it calls isPrime function in Util and receives if a boolean on whether the entered number is prime number. This unit test will show Pass status when the value received from isPrime is true.

Now add a Swift file with name as Util and make sure to select CheckForPrimeTests under Targets. This would ensure you can call functions written in Util class

201502082151.jpg

201502082152.jpg

Create a public class with name as Util and add function isPrime as shown below.

public class Util {

  

func isPrime(number:Int) -> Bool {

return number == 2

}

}

All we are doing here is to make sure the function validates number 2. Now executing unit test should show a green tick mark as shown below.

201502090829.jpg

Navigate back to TestsForUtil.swift and add second tests which checks for number 3.

  func testThreeIsPrime() {

let number:Int = 3;

XCTAssertTrue(Util().isPrime(number), “3 is a prime number”);

}

On executing this test you should notice failure message as we have hard coded isPrime function to work only for 2.

201502090831.jpg

And to make this test pass, we are going to check for 2 and 3 in isPrime function.

  func isPrime(number:Int) -> Bool {

return (number == 2) || (number == 3)

}

Let us add the unit test that checks for 4 which is not a prime number.

  func testFourIsPrime() {

let number:Int = 4;

XCTAssertFalse(Util().isPrime(number), “4 is not a prime number”);

}

We have used XCTAssertFalse as we are expecting isPrime to return false. This test would pass with out making any changes to isPrime function.

201502090838.jpg

Now let us add out next test case that checks for number 11.

  func testElevenIsPrime() {

let number:Int = 11;

XCTAssertTrue(Util().isPrime(number), “11 is a prime number”);

}

201502090841.jpg

We need to make changes to isPrime function so it returns true for number 11. But we cannot just keeping on hardcoding the numbers. So let us change the logic to handle all the prime numbers.

  func isPrime(number:Int) -> Bool {

  

var primeFlag:Bool = true

  

if ((number == 2) || (number == 3)) {

return primeFlag

}

  

if (number > 3) {

  

for index in 2…number-1 {

if (number % index == 0) {

primeFlag = false

break

}

}

}

  

return primeFlag

}

The above function would validate all prime and not a prime numbers and test written for number 11 should pass. Now you can write some tests for prime and not a prime number. For not a prime number make sure to use XCTAssertFalse.

  func testThirtyOneIsPrime() {

let number:Int = 31;

XCTAssertTrue(Util().isPrime(number), “31 is a prime number”);

}

  

func testFiftyIsPrime() {

let number:Int = 50;

XCTAssertFalse(Util().isPrime(number), “50 is not a prime number”);

}

Now let us check this logic for a negative number say -1. Negative numbers are not prime number so isPrime function should handle this. But this test would fail as we don’t have any check for negative numbers.

  func testMinusOneIsPrime() {

let number:Int = –1;

XCTAssertFalse(Util().isPrime(number), “-1 is not a prime number”);

}

Making a minor modifications to isPrime function should pass the test.

func isPrime(number:Int) -> Bool {

  

var primeFlag:Bool = true

  

if ((number == 2) || (number == 3)) {

return primeFlag

}

  

if (number > 3) {

  

for index in 2…number-1 {

if (number % index == 0) {

primeFlag = false

break

}

}

} else {

primeFlag = false

}

  

return primeFlag

}

And the test navigator in Xcode should show status for all your tests.

201502090920.jpg

The logic used in isPrime function can be improved and you can probably do that as your exercise. And make sure all the unit tests have green tick mark after changing isPrime function.

Download the source code from here.

Filed Under: Develop, Programming, Xcode Tagged With: Swift, TDD, Test Driven Development, Xcode

Integrating Stripe in Swift for iOS development

September 2, 2014 By Ravi Shankar 12 Comments

Stripe is payment gateway that can be integrated with any website and mobile apps. In this tutorial we will see a quick and simple integration of Stripe in Swift for iOS development using Stripe documentation for iOS.

201409021233.jpg

This hands on tutorial will help you to familiarise yourself in

  • Validating and creating token using Stripe IOS SDK
  • Installing third party library using Cocoa-pods (Stripe)
  • Calling Objective-C framework in Swift (Objective-C Bridging Headers settings)

Click File menu and select New -> Project

201409021049.jpg

Select Single View Application as the template for the project.

201409021050.jpg

Provide a name for your project and select the language as Swift.

201409021110.jpg

Now close the project in Xcode and launch terminal window.

Setup Stripe using Cocoa-pods

Run the following commands on your terminal window to install Stripe.

[code language=”plain”]sudo gem install cocoapods
pod init[/code]

Edit Podfile under project directory and add pod ‘Stripe’ then execute the below command in Terminal window.

[code language=”plain”]pod install[/code]

Navigate to the project folder and launch the file with extension as workspace. Now you should see the Stripe frameworks included under Pods directory along with your default project files.

201409021131.jpg

Write code to integrate Stripe

Edit ViewController.swift and add the following IBOutlet variable for the button.

[code language=”swift”]@IBOutlet var saveButton: UIButton![/code]

Now add the following variable declaration to ViewController.swift file to hold the instance of STPView class.

[code language=”swift”]var stripeView: STPView = STPView()[/code]

Since the Stripe framework has been written in Objective-C, we need to make sure to add the implementation file as part of the Objective-C bridging Headers under Build Settings.

Select Project folder and navigate to Build Settings. Then use the search field to locate to Objective-C Bridging Header setting.

201409021153.jpg

Then drag and drop the STPView.m file to Object-C Bridging Header section.

201409021155.jpg201409021156.jpg

Update the viewDidLoad function and add the following Stripe integration code. Make sure the ViewController class conforms to STPViewDelegate protocol

[code language=”swift”]class ViewController: UIViewController, STPViewDelegate{
override func viewDidLoad() {
super.viewDidLoad()
stripeView = STPView(frame: CGRectMake(15, 20, 290, 55), andKey: )
stripeView.delegate = self
view.addSubview(stripeView)
saveButton.enabled = false
}
}[/code]

 

The above lines of code will add the Stripe control that accepts credit card number, expiry date and code. The save button is by default disabled and will be enabled only after entering valid credit card number. Implement the following function that will be triggered after entering the card details. The boolean parameter in the function will indicate whether the user has entered a valid card information. Based on this value, the save button is enabled or disabled.

[code language=”swift”]func stripeView(view: STPView!, withCard card: PKCard!, isValid valid: Bool) {
if (valid) {
saveButton.enabled = true
} else {
saveButton.enabled = false
}
}[/code]

Add the following IBAction function which will be called on tap of the button. We are using STPView’s createToken function to generate token and a successful token will be written to the console window.

[code language=”swift”]@IBAction func saveButton(sender: AnyObject) {
stripeView.createToken { (stpToken, error) -&gt; Void in
if (error != nil) {
println(error)
} else {
println(stpToken)
}
}[/code]

Navigate to Main.storyboard and add UIButton from object library to ViewController. Centre align the button both horizontally and vertically to the View Controller.

201409021138.jpg

Then use Connection Inspector to connect the button to IBOutlet variable and saveButton function to Tap Up Inside event of the button.

201409021228.jpg

Now build and run the project on simulator and you can use dummy card number 4242 4242 4242 4242 to test your implementation. For more details refer to Stripe Testing Documentation.

Sample Output

[code language=”plain”]Successful token – tok_14YBF42eZvKYlo2CoZtuO3Md (test mode)

Error message – Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo=0x7f9b7147b4a0 {NSUnderlyingError=0x7f9b71786ca0 "The Internet connection appears to be offline.", NSErrorFailingURLStringKey=https://pk_test_6pRNASCoBOKtIshFeQd4XMUh:@api.stripe.com/v1/tokens, NSErrorFailingURLKey=https://pk_test_6pRNASCoBOKtIshFeQd4XMUh:@api.stripe.com/v1/tokens, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSLocalizedDescription=The Internet connection appears to be offline.}[/code]

Download Demo Project from GitHub

Filed Under: Develop, ios, iPhone, Programming Tagged With: Stripe, Swift

Quotes app – Simple page based application in Swift

August 13, 2014 By Ravi Shankar 8 Comments

This is a very basic tutorial on how to create a simple page based app in Swift. We are going to use Page Based Application project template for displaying quotes in different pages.

201408131144.jpg201408131148.jpg

 

Create Page-Based Application in Swift

Click Xcode File menu, navigate to New and select Project from sub menu list.

201408131151.jpg

Select Page-Based Application in template screen and click Next button.

201408131152.jpg

In the Project Options screen, provide a name for your project and select language as Swift. Then click Next button and save your project.

201408131154.jpg

This should create a default page based application in Swift with the following project structure.

201408131156.jpg

Run the project on Simulator should display a page based app displaying names of months. When you tap or swipe the screen, next page should be displayed.

201408131159.jpg

Modifying the default Page-based application

We are going to modify the existing app to display quotes instead of months. The default project follows MVC pattern for retrieving and displaying the data. RootViewController.swift does the controller part, DataViewController.swift/Storyboard is used for displaying Views and ModelViewController.swift provides the data.

Let us first start with the changes to Storyboard. Navigate to Main.storyboard, select and delete the View and Label under Data View Controller.

201408131217.jpg

Set the background colour of the View to Purple using Attributes Inspector.

201408131220.jpg

Drag and drop a UILabel from Object library on to View Controller. Make sure to Centre align the label both vertically and horizontally.

201408131231.jpg

Use the Attributes Inspector to set the colour, alignment and Font for UILabel’s Text. Then change the number of lines displayed in UILabel to 3. Next use the align option in Interface builder to add the Horizontal and Vertical Center constraints (select Use Current Canvas Value)

201408131246.jpg

Click Connection Inspector and connect dataLabel to the newly added UILabel. dataLabel property was already added to the DataViewController.swift to display month name.

201408131250.jpg

Make changes to ModelViewController

Now we need to provide the required data for the display. Click ModelViewController.swift and change the pageData variable in to a constant and add array of four quotes as shown below.

[code language=”swift”]let pageData:NSArray = ["I’m as proud of what we don’t do as I am of what we do – Steve Jobs", "That’s one small step for man, one giant leap for mankind – Neil Armstrong","An ant on the move does more than a dozing ox – Lao Tzu","I mean, it’s impossible But that’s exactly what we’ve tried to do – Jonathan Ive"]
[/code]

 

Then delete the following lines from init() function

[code language=”swift”]// Create the data model.

let dateFormatter = NSDateFormatter()

pageData = dateFormatter.monthSymbols[/code]

 

Now compile and run the app on the simulator to see a Simple Page-based app in action written in Swift.

201408131315.jpg

Since we had gone with the default page-based template, we are unaware of the logic behind UIPageViewController. In another post, I will try to build a UIPageViewController from scratch without using the template and see more about the UIPageViewControllerDelegate and UIPageViewControllerDataSource.

Download source code from here

Filed Under: Develop, iPhone, Programming, Xcode Tagged With: PageBaed App, Swift, Xcode

  • « Go to Previous Page
  • Go to page 1
  • Go to page 2
  • Go to page 3
  • Go to page 4
  • Go to Next Page »

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