Swift – Structs

If you haven’t heard Swift is a new language from Apple. Swift aims to be a modern language that streamlines your work.

Swift is strongly typed. This means that every value in Swift must be assigned a type.

Here I would like to talk about one feature in Swift called Structs. Struct is short for Structure or Construct. A Struct is similar to an Object in JavaScript.

In Swift a Struct is value. You can think of it as a complex value. If you were to think of a typical value, in a variable you might think:

var x = 230

Here you have a single name, x, representing a single value the number (Int) 230. A Struct is the same, with the difference that a Struct is a structure containing more than a single value. You can think of the difference conceptually as the difference between: nail, and house. Nail is a single discrete element, while a house is single structure, it contains many sub elements.


var nail = 1
struct House {
    var nails = 23000
    var boards = 1200
}

You can see the variable nail holds a single value, while the house has two values: nails, and boards, and could contain any number of other values, like doors, switches outlets etc. Think of a Struct as a way to define an element that contains a group of related values. Imagine everything in your house as a struct:

struct House {
    var nails = 1000
    var boards = 200
    var lightSwitches = 4
    var doors = 3
    var sink = 1
    var toilet = 1
}

var myHouse = House()
println(myHouse.boards)

Structs can also contain functions. In many ways a Struct is similar to a class. From our perspective they act in very much the same ways. Internally the software works them. Structs are assigned as values and Objects created from a Class are assigned as reference.

Copy vs Reference

When assigning a value (this would be how Structs are passed around) the computer creates a copy of the Struct. When you assign an Object you are assigning a reference to the original Object. In short:

Structs are always copied when they are assigned.

Class Objects are not copied when they assigned.

For example:


struct House {
    var address = "123 Maple St."
}

var a = House()
var b = a 
b.address = "321 Elm St."

println(a.address) // prints 123 Maple St.
println(b.address) // prints 321 Elm St.

Here you have two separate Houses. The first (a) would have the address 123, the second would have the address 321.

Here’s what would happen with a Class


class House {
    var address = "123 Maple St"
}

var a = House()
var b = a 
b.address = "321 Elm St."

println(a.address) // prints 321 Elm St.
println(b.address) // prints 321 Elm St.

You have two references to the same house, which moved from it’s original address to the 321 address.

Here is what Apple has to say about structs: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html

Swift – Character vs String

In Swift everything has a type. And these types can be fairly detailed. For example, Swift makes a clear distinction between a single Character, and a Collection of Characters.

Character

A Character in Swift can be any Character, this includes Emoji characters, and any other special character from any language set. You aren’t limited to UTF-8 characters.

Like many other programming languages Swift allows an escape sequence to represent special characters like these:

  • \n Line Feed
  • \r Carriage return
  • \t Tab stop
  • \\ Backslash

Characters also have a Name which describes the Character. For example a might be LATIN-SMALL LETTER A, while an Emoji might be FRONT-FACING BABY CHICK.

String

A String is a collection of Characters. The String has methods that allow us to access each Character in the String, and modify those Characters.

The String Class has so many options I couldn’t list them all here. All of the standard features you would expect exist. Though they might some different names. Things like:

  • substringFromIndex
  • substringToIndex
  • stringByReplacingCharactersInRange
  • stringByReplacingOccurrencesOfString

Swift – Enum

Organizing Code with Enums

Often when programming you keep track of fixed sets of things. These could be choices like how you will view something, for example Year, Month, Week, or Day. Other sets might be related to the capabilities of your app like the orientation: Portrait, Landscape. Or it could be a list enemy or character types a game might create. Another example might be the colors of tags that an app might use to organize elements.

When creating these things you look for ways to organize them. Often they end up in lists or arrays. While this works well there are some limits and awkward situations that arise. For example if you created a list of colors:

tagColors = [Red, Orange, Yellow, Green, Blue]

You would need to access these colors via their index. Which is awkward. For example:

tagColors[0] // Red

There is also a problem in that your tag colors might be fixed, the Array provides many methods that allow the list to be modified. While you can work around many of these things, there is also ready made construct for this purpose the Enum.

The Enum

Enum or Enumeration is similar to a Struct though more limited. Enums provide a system for creating variables that have very specifically defined values. Use an enum when you want to ensure that a predefined set of values are used.

For example, imagine your program wants to set the colors of some tags. The colors are predefined as: Red, Orange, Yellow Green, Blue, and Purple, an Enum provides a perfect way to keep these organized, while also making your code more organized and easier to work with.

Named Values and Enums

Names like Red, and Green work well in code. Writing the actual color in code is difficult to work with.

  • #b32f3c – Red
  • #f8941d – Orange
  • #e7d936 – Yellow
  • #39b54a – Green
  • #0072bc – Blue
  • #92278f – Purple

Just looking at this it’s really hard to tell Yellow: #e7d936 from Green: #39b54a.

Working with these colors in Xcode there is the added problem that you will most often want a UIColor() which requires more than knowing the hex value. So the colors above might actually look like this in code:

  • UIColor(red: 179, green: 47, blue: 60, alpha: 1) – Red
  • UIColor(red: 248, green: 148, blue: 29, alpha: 1) – Orange
  • UIColor(red: 231, green: 217, blue: 54, alpha: 1) – Yellow
  • UIColor(red: 57, green: 181, blue: 74, alpha: 1) – Green
  • UIColor(red: 0, green: 114, blue: 188, alpha: 1) – Blue
  • UIColor(red: 146, green: 39, blue: 143, alpha: 1) – Purple

To make make a UIColor out of Red we need to write something like:

UIColor(red: 179, green: 47, blue: 60, alpha: 1)

That’s a lot to write. If it were used more than once in our program, and it probably will be, there will be a lot of code for us to write, which translates into more chances for errors, and difficulty in making changes.

You might also want the Hex value: #b32f3c, at another point, and the color name: Red at another time. You might want to display a table cell, set the background to the color, with UIColor(), you may also want to display the tag name: Red on the right side. Both of these items are tied together and related. To work with them in code we want the same type of relationship. We want to talk about Red, and have that mean the UIColor(), and the name, and anything else associated with Red. An Enum is a programming structure in Swift that is made for exactly this.

enum TagColor {
    case Red, Orange, Yellow, Green, Blue, Purple
}

This is an Enum named: TagColor, it defines 6 named values. You can put each on it’s own line also:

enum TagColor {
    case Red
    case Orange
    case Yellow
    case Green
    case Blue
    case Purple
}

Any variable can now hold a reference to one of the colors.

var myColor = TagColor.Red

You can Type something as TagColor

var aColor: TagColor

Now you have to assign this item a TagColor.

aColor = TagColor.Blue

If something is typed to an Enum you can shorten the value to a dot and the name:

aColor = .Blue

Methods in an Enum

An Enum can contain methods. Using a method your Enum can return a UIColor object for each color. Use a switch statement that returns a UIColor for each of the enum keywords  we defined. This switch statement must provide a case for all of the key words. For example add function called toUIColor, that returns a UIColor:

func toUIColor() -> UIColor {
switch self {
    case .Red:
        return UIColor(red: 179, green: 47, blue: 60, alpha: 1)

    case .Orange:
        return UIColor(red: 248, green: 148, blue: 29, alpha: 1)

    case .Yellow:
        return UIColor(red: 231, green: 217, blue: 54, alpha: 1)

    case .Green:
        return UIColor(red: 57, green: 181, blue: 74, alpha: 1)

    case .Blue:
        return UIColor(red: 0, green: 114, blue: 188, alpha: 1)

    case .Purple:
        return UIColor(red: 146, green: 39, blue: 143, alpha: 1)

    }

}

Call a method in an Enum like this:

TagColor.Blue.toUIColor()

or

var aColor = TagColor.Orange.toString() // Returns String UIColor

Here are all of the things above in a playground.

import UIKit

enum Suit {
    case Spades, Hearts, Diamonds, Clubs
}

enum Colors {
    case Red, Yellow, Green, Cyan, Blue, Magenta
    
    func toHex() -> String {
        switch self {
        case .Red:
            return "#FF0000"
        case .Yellow:
            return "#FFFF00"
        case Green:
            return "#00FF00"
        case .Cyan:
            return "#00FFFF"
        case .Blue:
            return "#0000FF"
        case .Magenta:
            return "#FF00FF"
        }
    }
}

var red = Colors.Red.toHex()
println("Color:\(Colors.Red.toHex())")

enum TagColor {
    case Red, Orange, Yellow, Green, Blue, Purple
    
    func toUIColor() -> UIColor {
        switch self {
        case .Red:
            return UIColor(red: 179, green: 47, blue: 60, alpha: 1)
        case .Orange:
            return UIColor(red: 248, green: 148, blue: 29, alpha: 1)
        case .Yellow:
            return UIColor(red: 231, green: 217, blue: 54, alpha: 1)
        case .Green:
            return UIColor(red: 57, green: 181, blue: 74, alpha: 1)
        case .Blue:
            return UIColor(red: 0, green: 114, blue: 188, alpha: 1)
        case .Purple:
            return UIColor(red: 146, green: 39, blue: 143, alpha: 1)
        }
    }
    
    func toHex() -> String {
        switch self {
        case .Red:
            return "#b32f3c"
        case .Orange:
            return "#f8941d"
        case .Yellow:
            return "#e7d936"
        case .Green:
            return "#39b54a"
        case .Blue:
            return "#0072bc"
        case .Purple:
            return "#92278f"
        }
    }
    
    func toString() -> String {
        switch self {
        case .Red:
            return "Red"
        case .Orange:
            return "Orange"
        case .Yellow:
            return "Yellow"
        case .Green:
            return "Green"
        case .Blue:
            return "Blue"
        case .Purple:
            return "Purple"
        }
    }
}

var myTag = TagColor.Red
var yourTag = TagColor.Green
var aColor: TagColor

aColor = .Blue

TagColor.Blue.toString()

println(myTag.toHex())
println(myTag.toUIColor())
println(myTag.toString())

// A function that takes an enum value
func makeTag(color: TagColor) {
    println("makes a tag of color:\(color.toString())")
}

makeTag(TagColor.Purple)

// If the type is an enum you can shorten to a dot and the keyword name
makeTag(.Green)