Properties

It is best to let Swift infer the variable type. Many types are Optionals.

Constants and Variables

Type will be inferred

let immutableInferInt  = 42    // a constant
var mutableInferDouble = 125e2 // int variable
var mutableInferFloat  = 1.0   // float variable
var mutableInferString = "This is a" + " String"
var mutableInferString = "The answer is \(immutable_var)"

Type is given specifically

var mutableDouble   : Double = 1.0
var mutableInt      : Int    = 1
let immutableBool   : Bool   = false
let immutableString : String = "Text" // String is always an optional

Type Conversion

With init()

led d: Double = 37.5
let f: Float  = 37.5
let x = Int(d)       // truncates
led xd = Double(x)
let cgf = CGFloat(d)

let a = Array("abc")            // a = ["a", "b", "c"], array of characters
let s = String(["a", "b", "c"]) // s= "abc"

let s = String(52)  // no floats
let s = "\(37.5)"

Property Observer willSet& didSet

A property can have two observer functions. They can be used to inform somebody that the variable "will get set" or "did just get set".

  • Can be used to update the GUI
    var userStatusText: String {
      willSet {
          print("About to set status to:  \(newValue)")
      }
      didSet {
          if userStatusText != oldValue {
              postNewStatusNotification()
          }
      }
    }
    

lazy

  • lazyproperties are not getting initialized until someone accesses it
  • only for var
lazy var varName = SomeClass() // Nice if SomeClass uses a lot of resources

lazy var someProperty: Type = {
   // construct the value
   return constructed value
}()

lazy var myProperty = self.initializeMyProperty()

String

String is an array of character. But one String can need one or more characters (glyphs) Combining Strings

let string1 = "one"
let string2 = "two"
var combinedString = "\(string1) \(string2)" + " three"

String Conversion

var intString = "999"
var intVar = NSString(string: intString).intValue           // == 999

var doubleString = "9.95"
var Double_var = NSString(string: doubleString).doubleValue // == 9.95

String Functions

var s     = "hello"
let index = advance(s.startIndex, 2) // String.Index to the 3rd glyph "l"
s.splice("abc", index)               // s will now be "heabcllo"

let startIndex = advance(s.startIndex, 1)
let endIndex   = advance(s.startIndex, 6)
let substring  = s[index..<enIndex]  // substring will be "eabcl"

let num = "12.34"
if let decimalRange = num.rangeOfString(".") { // decimalRange == Range<String.Index>
    let wholeNumberPart = num[num.startIndex..<decimalRange.startIndex]
}
//Also
s.removeRange([s.startIndex..<decimalRange.startIndex])
replaceRange(Range,String)

Optional

An Optional is just en enum.

enum Optional<T> {
    case None
    case Some(T)
}

Examples:

let x: String? = nil
// ==
let x: = Optional<String>.None

let x: String? = "Hello"
// ==
let x = Optional<String>.Some("Hello")

var y = x!
// ==
switch x {
    case Some((let value): y = value
    case None: //raise and exception
}

Closures

A closure capture variables in the surrounding context

class Grapher {
    var yforX: ((x:Double) -> Double?)?
}

let grapher = Grapher()
let graphingBrain = CalculatorBrain()
graphingBrain.program = theProgramToGraph
grapher.yForX = { (x:Double) -> Double? in
    graphingBrain.variableValues["M"] = x
    return graphingBrain.evaluate() // gets captured and reused each time yForX is called
}

Capture Danger There can be memory management problems. It can create a memory cycle. Closures capture pointers back at the closure. There will always be a pointer to the closure and to the captured thing, neither will ever be able to leave the heap.

class Foo {
    var action: () -> Void = {}
    func show(value: Int) {println("\(value)")}
    func setupMyAction() {
        var x:  Int = 0
        action = {                    // capture danger
        action = { [unowned self] in  // working because of unowned

            x = x + 1
            self.show()
        }
    }
    func doMyAction10times() {
        for i in 1..10 { action() }
    }
}

self has a pointer to the closure and closure has a pointer to the x (self) They can never be released, therefore you need to specify the unowned keyword.

Array

An Array is a list of multidimensional elements of the same type

var arr = Array<String>()
// ==
var arr = [String]()

Out of bounds

//             0       1          2
let os_s ["Linux",  "Mac", "Windows"]
let os      = os_s[0]     // "Linux"
let os      = os_s[2]     // "Windows"
let os      = os_s[3]     // crash index out of bounds
let some_os = os_s[0...1] // ["Linux", "Mac"]

Enumerating and Array

for os in os_s {
    println("\(os)")
}

Array Functions

var a = [a,b,c]

arr.append(T)
arr.insert(T, atIndex: Int)           // a.insert(d, atIndex:1), a=[a,d,b,c]
arr.splice(Array<T>, atIndex: Int)    // a.splice([d,e], atIndex:1), a= [a,d,e,b,c]

removeAtIndex(Int)                    // a.removeAtIndex(1), a = [a,c]
removeRange(Range)                    // a.removeRange(0..<2), a= [c]
replaceRange(Range, [T])              // a,replaceRange(0...1, with:[x,y,z]), a = [x,y,z,b]

sort(isOrderedBefore: (T, T) -> Bool) // a.sort { $0 < $1 }

filter(includeElement: (T) -> Bool) -> [T]
map(transform: (T) -> U) -> [U]
let stringfield: [String] = [1,2,3].map { "\($0)" }

reduce(initial: U, combine:(U,T) -> U) -> U
let sum: Int = [1,2,3].reduce(0) { $0 + $1 }

Dictionary

Dictionaries are list of values search-able with a key

var dict = Dicrionary<String, Int>()
// ==
var dict = [String:Int]()
var regions = ["wallis":1, "fribourg":10]
let rank = regions["bern"] // doesn't exist would be Int! therefore nil
regions["fribourg"] = nil  // delete fribourg

Use a tuple with for-in to enumerate a dictionary

for (key, value) in regions {
    println("\(key) = \(value)")
}

Range

A Range in Swift are just two points of a type. Can be represented as:

struct Range <T> {
    var startIndex: T
    var endIndex  : T
}
Type Range
Array Range<Int>
String Range<String.Index>

There is a special syntax for defining a range: ... or ..<

//            0    1    2    3
let array = ["a", "b", "c", "d"]
let subArray1 = array[2...3] // ["c", "d"]
let subArray2 = array[2..<3] // ["c"]

Range is also enumerable

for in 24...42 {}