Tuesday, April 28, 2015

iOS touch events with Swift version 1.2

Prior to the 1.2 version of Swift, the touchesBegan(), touchesMoved() and touchesEnd() methods used the NSSet type to store the collection of UITouch instances that represent the touches.  In version 1.2 of Swift, Apple introduced the new native Set type and replaced the NSSet type in the touchesBegan(), touchesMoved() and touchesEnd() methods with this new Set type.  With this change we can no longer access the UITouch instances in the same way that we did prior to version 1.2.

Touch events prior to version 1.2
Prior to version 1.2 of Swift, I used the following code to access a single UITouch instances from the NSSet collection.

override func touchesBegan(touches: NSSet, withEvent event: UIEvent)  {
   if let touch = touches.anyObject() {
       lastPoint = touch. locationInView(self)

   }
}

This will now throw the following error:

Overriding method with selector 'touchesBegan:withEvent:' has incompatible type '(NSSet, UIEvent) -> ()'

Touch events starting with version 1.2
The following code demonstrates how we would want to access a single UITouch event with version 1.2 of Swift.

override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
    if let touch = touches.first as? UITouch {
        lastPoint = touch.locationInView(self)
    }
}

If we wanted to cycle though all of the touch events we would use the following code:

for touch in touches  {
    var myTouch = touch as? UITouch
    //code here 
}


While this change did take people by surprise; the overall addition of the Set type out weights the headache of these changes.  If you want to read more about the new Set type, see my blog post here: http://masteringswift.blogspot.com/2015/04/swift-native-set-type.html

Swift native Set Type

When the 1.0 version of Swift was initially released it contains native String, Array and Dictionary types that were bridged with the NSString, NSArray and NSDictionary types.  The one noticeable omission was Swift did not contain a native set type.  With the 1.2 version of Swift, Apple corrected this omission and added the Set type.

The Set type is a generic collection that is similar to the Array type.  Where the Array type is an ordered collection that may contain duplicate items, the Set type is an unordered collection where each item must be unique.

Lets look t how we would use the Set type.

Initializing a set
There are a couple of ways that we can initialize a set.  Just like the Array and Dictionary types, Swift needs to know what type of data is going to be stored in it.  This means that we must either tell Swift the type of data to store in the set or initialize it with some data so Swift can infer the data type.

Just like the Array and Dictionary types, we use the var and let keywords to declare if the set is mutable or not.  If a set is declared using the var keyword than it is mutable and if it is declared with the let keyword than it is not mutable.

//Initializes an empty Set of the String type
var mySet = Set<String>()

//Initializes a mutable set of the String type with initial values
var mySet = Set([“one”, “two”, “three”])

//Creates a non-mutable set of the String type.
let mySet = Set([“one”, “two”, “three”])

Inserting items into a Set
We use the insert method to insert an item into a set.  If we attempt to insert an item that is already there, the item will be ignored and no error will be thrown.  Here are some examples on how to insert items into a set.

var mySet = Set<String>()
mySet.insert(“One”)
mySet.insert(“Two”)
mySet.insert(“Three”)

Number of items in a Set
We can use the count property to determine the number of items in a Swift Set.  Here is an example of how to use the count method.

var mySet = Set<String>()
mySet.insert(“One”)
mySet.insert(“Two”)
mySet.insert(“Three”)
println(“\(mySet.count) items”)
The previous code will print the message “3 items” to the console because the set contains three items.

Check if a Set contains an item
We can very easily check to see if a Set contains an item by using the contains() method as shown here. 

var mySet = Set<String>()
mySet.insert(“One”)
mySet.insert(“Two”)
mySet.insert(“Three”)
var contain = mySet.contains(“Two”)
In the previous example, the contain variable is set to True because the set does contain the String “Two”.

Iterating over a Set
We can use the for statement to iterate over the items in a Set.    The following example shows how to use the for statement to iterate though the items in a set.

for item in mySet {
    println(item)
}
The previous example would print out each item in the set.

Removing items in a Set
We can remove a single item or all items in a set.  The following example shows how to remove items from a set.

//The remove method will return and remove an item from a set
var item = mySet.remove(“Two”)

//The removeAll method will remove all items from a set
mySet.removeAll()


Set Operations
Apple has provided four methods that we can use to construct a set from two other sets.  These operations can either be performed in place, on one of the sets, or used to create a new set.    These operations are:

union and unionInPlace:  Creates a set with all unique vales from both sets
subtract and subtractInPlace:  Creates a set with values from the first set that are not in the second set:
intersect and intersectInPlace:  Creates a set with values that are common to both sets
exclusiveOr and exclusiveOrInPlace:  Creates a new set with values that are in either set but not in both sets.

Lets look at some examples and see what results we get from each of these operations.  For all examples we will be using the following two sets:

var mySet1 = Set(["One", "Two", "Three", "abc"])
var mySet2 = Set(["abc","def","ghi", "One"])

Now lets look at our examples:

//newSetUnion = {"ghi", "Two", "One", "Three", "abc", "def"}
var newSetUnion = mySet1.union(mySet2)

//newSetSubtract = {"Two", "Three"}
var newSetSubtract = mySet1.subtract(mySet2)

//netSetIntersect = {"One", "abc"}
var newSetIntersect = mySet1.intersect(mySet2)

//newSetExclusiveOr = {"Two", "Three", "def", "ghi"}
var newSetExclusiveOr = mySet1.exclusiveOr(mySet2)


These four operations (union, subtract, intersect and exclusiveOr methods) add additional functionality that are not present with arrays.  Combine that with the faster lookup speeds as compared to an array, the Set can be a very useful alternative when the order of the collection is not important and the objects in a collection must be unique. 

Saturday, April 11, 2015

Generics Functions in Swift

For developers that have used the Java or C# programming languages, Generics in Swift should look pretty familiar because Swift’s implementation is very similar to those languages.  For other developers Generics may seem a bit foreign at first.

Before we look at how to use Generics in Swift, let’s take a look at the problem that they are designed to solve.  Lets say that we wanted to write a function that swapped the values of two Int types.  We could very easily write the function like this:

func swapInts (inout x: Int, inout y: Int) {
    let tmp = x
    x = y
    y = tmp
}

Now lets say that we also have a need to swap the values of two String types.  We could then write another function like this:

func swapString (inout x: String, inout y: String) {
    let tmp = x
    x = y
    y = tmp
}

Having two functions like this isn’t too bad but what if we also had a need two swap two UInt, Double and Boolean types as well?  This could get out of hand very quickly.   The worse part is we are duplicating most of the code each time we add a new swap function.  This is where Generics can help us.

Generics allow us to write flexible and reusable code that avoids the duplication that we saw in the previous examples.  Now lets look at how we could write one function with Generics that would allow us to swap the values of any data type. 

func swapGeneric<T> (inout x: T, inout y: T) {
    let tmp = x
    x = y
    y = tmp
}

The swapGeneric() function looks pretty similar to the other two swap functions that we saw earlier except for the capital T.  The capital T is used as a placeholder and lets Swift know that we will be defining the type, associated with the placeholder, at run time.  When we define a Generic function we include the placeholder between two angled brackets (<>).  We can then use that placeholder in place of any type definition within the function, the function’s definition or as the return type of the function.

There is nothing special about the capital T that we used in our example.  We can actually use any valid identifier but generally we use a capital T or a capital E.
We would use the genericSwap() function like this:

var a = 1.1
var b = 2.2
swapGeneric(&a, &b)
println("a = \(a)  b = \(b)")


var c = "One"
var d = "two"
swapGeneric (&c, &d)
println("c = \(c) d = \(d)")

In these examples, we see that we can swap two Double types or two String types with the same swapGeneric() function.  We could expanded these examples to include any data type that we want.
We are also not limited to using just a single generic type.  Lets look at an example of where we use two generic types.

func printValue<T,E> (value1: T, value2: E) {

    println("value1:  \(value1)")
    println("value2:  \(value2)")
}

In this function we have two generic types defined, the T and the E.  Here are a couple of examples of how we could use this function.

printValue(“hello”, 1234)
printValue(3.1415, “bye”)

We can see that we can include different data types within the parameters that we are sending to the printValue() function.

In this post, we briefly looked at how we could use Generics within a function definition to create a function whose parameter types can change at runtime as needed.  This is one of the most popular uses for Generics and is also the basis of Swift’s collection types (Array, Dictionary).  For a more in-depth discussion of Generics and how to create Generic and Associated types, check out my book Mastering Swift published by Packt Publishing.


Tuesday, April 7, 2015

Swift as a scripting language

I have been using Swift since it was first announced at the WWDC in 2014 and I can honestly say that it has quickly become my favorite programming language.  One of the really great features of Swift is its ability to be used not only as a compiled language but also as a scripting language.  This allows us to execute Swift scripts without the need to compile them first and outside of XCode.  In this post we will look at how to create and execute Swift scripts.

Lets start off by creating a simple Hello World script that will print the standard “Hello World” message to the console.  We will start by opening our favorite text editor (for me that is VI or UltraEdit) and create a file named hello.swift which contains the following code:

#!/usr/bin/env xcrun swift
println(“Hello World”)

The file, as it is currently saved, is not executable. Therefore before we can run it we need to make it executable.  To do this we need to open a terminal window (Applications->Utilities->Terminal) and change to the directory that our hello.swift file is in.  We then execute the following command to make the file executable:

chmod +x hello.swift

Now the file is executable and we can execute it with the following command from the terminal prompt in the directory that the hello.swift file is located in:

./hello.swift

If we run this command we should see the “Hello World” message printed to the console.  This is pretty cool but also pretty basic.  Now the question is can we accept a command line arguments and change the greeting to say hello to different people?  Of course we can. 

Similar to other languages, Swift creates an argument count variable and an argument value array that tell us the number of command line arguments and also the values.  These are:
  • C_ARGC:  The number of arguments passed in
  • C_ARGV:  An array of the arguments values

Lets see how to use these by creating another file named hello2.swift and put the following code in it.

#!/usr/bin/env xcrun swift

var name = "World"
if (C_ARGC > 1) {
    if let arg1 = String.fromCString(C_ARGV[1]) {
        name = arg1
    }
}
println("Hello \(name)")

Don’t forget to make the script executable using the chmod command that we showed earlier.
We begin this script by creating a variable named name which contains the string “World” by default.  

We then see if any command line argument were entered.  Notice that we are checking to see if there was more than one command line argument entered because the first command line argument is always the name of the file that we are running therefore the second command line argument would contain the name of the person to greet.  For example, if we ran the script like this:

./hello2.swift one two three

The C_ARGC[] array would contain the following data:
  • C_ARGC[0] = ./hello2.swift
  • C_ARGC[1] = one
  • C_ARGC[2] = two
  • C_ARGC[3] = three

If we have more than one command line argument we then use the fromCString() method to convert the command line argument to a Swift String.  We can use the fromCString() method because of the automatic bridging between the Swift String type and the NSString class.  We then set the name variable to this new string.

Finally we print out the greeting to the console.  The following example shows how we would run this script from a terminal prompt:

./hello2.swift Jon

The following example would print out the message “Hello Jon” to the console.

Lets look at one final example.  This example will accept one command line argument, which should be the path and file name of a text file.  The script will then print out the contents of the file to the console.  This is similar to the basic functionality of the cat command therefore we will call this script cat.swift.  Here is the code for the script. 

#!/usr/bin/env xcrun swift

import Foundation
let file = ""

if (C_ARGC > 1) {
    if let file = String.fromCString(C_ARGV[1]) {
        if let fileContent = NSString(contentsOfFile: file, encoding: NSUTF8StringEncoding, error: nil){

            println(fileContent)
        }
    }

} else {
    println("Requires a filename")
}

This example is similar to the hello2.swift example accept instead of printing a greeting to the console we create a String type that contains the contents of a file.  To do this we use the init(contentsOfFile,encoding,error) initiator to create the String type.  We then print the contents of that file to the console.

I spent many years as a Unix/Linux System Administer and this required me to become very adept at creating shell scripts.  While shell scripts and other scripting languages can be very powerful, they also have limitations.  Using Swift as a scripting language, with the Foundation library and Cocoa APIs, opens up all kinds of scripting possibilites.  It also allows us to write scripts in the same language that we use for our OS X and iOS development.