cs193p – Lecture #4 – More Swift and Foundation Frameworks

cs193p - Lecture #4 - More Swift and Foundation Frameworks

Please note, this blog entry is from a previous course. You might want to check out the current one.

Lecture #4 has no demo only theory:


Optionals are like enums:

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


let x: String? = nil


let x = Optional<String>.None


let x: String? = "hello"


let x = Optional<String>.Some("hello")

Unwrapping the optional like

var y = x!

would mean for the enum:

switch x {
  case Some(let value): y = value
  case None: // raise an exception 


var a = Array<String>()

is the same as

var a = [String]()

Trying to append an immutable array (let) will not compile.
Accessing a not existing index will produce a crash.


var pac10teamRankings = Dictionary<String, Int>()

is the same as

var pac10teamRankings = [String:Int]()

Accessing an item of the dictionary returns an optional, because the result could be nil for a not existing key.

To enumerate a dictionary use tuples, e.g.:

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


Ranges are defined by its endpoints of “sensible” type with a pseudo-representation like:

struct Range<T> {
  var startIndex: T
  var endIndex: T

2…4 defines a range including the endpoints (2,3,4).
2..<4 defines an open ended range not including the endpoint (2,3)

Ranges are enumeratable, e.g.:

for i in [27...104] { }

Other Classes

  • NSObject … manly to interface with Objective-C classes
  • NSNumber … generic number class
  • NSDate … to cope with dates and time … see also NSCalendar, NSDateFormatter, NSDateComponents
  • NSData … used to save, restore, or transmit raw data

Data Structures

Swift uses classes, structures and enumerations which are quite similar:

    Declaration Syntax

    class CalculatorBrain {}
    struct Vertex {}
    enum Op {}

    Properties and Functions

    func doit(argument: Type) -> ReturnValue {}
    var storedProperty = <initialValue> // not for enums
    var computedProperty: Type { get {} set {} }

    Initializers (not for enums)

    init(argument1: Type, argument2: Type, ...) {}

    However only classes have inheritance, introspection and casting. Structs and enums are value types. Classes are reference types.

    Value Types

    • are copied when passed to a function,
    • are copied when assigned to another variable,
    • and are immutable when assigned using let.

    Note that function parameters are constants by default. Using var for a parameter creates a mutable copy. Any function which can mutate a struct or enum needs to marked with the keyword mutating.

    Reference Types

    • are stored in the heap,
    • and are mutable when passed to a function, even if constant (let) pointers are used.

    Usually choose classes. Use structures for fundamental types and enumerations for data with discrete values.


    To override a method or property of the parent class mark them with the keyword override. To prevent subclasses from overriding add the keyword final.

    To define a type method add the keyword static or class respectively.

    All parameters have an internal (used within the method) and an external name (used by the caller):

    func foo(external internal: Int) {
      let local = internal
    func bar() {
      let result = foo(external: 123)

    To omit the external name use an underscore “_” instead – which is the default for the first parameter (but the init method). To force the same internal and external name for the first parameter use the hash sign e.g. “#internal“. For all other parameters the internal and external names are the same by default. Omitting (“_”) the external names for any but the first parameter is “anti-Swift”.


    Property Observers

    You can observe the changes to any property using willSet and didSet where newValue and oldValue provide access to the the future or previous values.

    Lazy Initialization

    Properties marked with “lazy” only get initialized when they are accessed the first time.


    init methods are normally not used, if values can be set using defaults, they are optionals, they are initialized using closures, or by lazy initialization.

    Inside an init you can

    • set any property, even those with default values,
    • set constant properties,
    • call other init methods of the same class
    • or call init methods of the parent class

    You are required to

    • set all properties before the init is done or an init of the parent class is called,
    • from a designated init call only a designated init of the immediate parent class,
    • call a parents init before assigning an inherited property,
    • and from a convenience init call a designated init of the same class (or at lease call it indirectly through another convenience init) before setting any property.

    If you do not implement any designated init, you inherit all of its parent designated inits.
    If you override all designated inits of the parent, you inherit all convenience inits.
    If you override no inits, you inherit all inits.

    Inits marked as required must be implemented by any sub class.

    Inits marked with a question or exclamation mark return optionals.


    This special protocols is primarily used for compatibility with existing Objective-C-based APIs.

    To cast AnyObject (or any other type) to a specific type us “as” or “as?“, or to check before casting “is“.

    Array<T> Methods

    += [T]                         // add another array
    first -> T?                    // get first element
    last -> T?                     // get last element
    append(T)                      // add element
    insert(T, atIndex: Int)        // insert element
    splice(Array<T>, atIndex: Int) // insert array
    removeAtIndex(Int)             // remove element
    removeRange(Range, [T])        // remove range of elements
    sort(isOrderedBefore: (T,T) -> Bool) // sort array
    // filter out undesired elements
    filter(includeElement: (T) -> Bool) -> [T]
    // transform array into new array
    map(transform: (T) -> U) -> [U]
    // reduce array to single value
    reduce(initial: U, combine: (U, T) -> U) -> U


    A string is not an array of characters!

    // get index of 3rd glyph
    let index = advance(s.startIndex, 2)
    // insert charaters 
    s.splice("abc", index)
    // get start position
    let startIndex = advance(s.StartIndex, 1)
    // get position of 6h glypth
    let endIndex = advance(s.StartIndex, 6)
    // get sub string
    let substring = s[index..<endIndex]
    // get whole-number part of double
    let num = "56.25"
    if let decimalRange = num.rangeOfString(".") {
      let wholeNumberPart = num[num.startIndex..<decimalRange.startIndex]
    // remove the whole-number part
    replaceRange(Range, String) // replace part of an string
    // more methods
    description -> String
    endIndex -> String.Index
    hasPrefix(String) -> Bool
    hasSuffix(String) -> Bool
    toInt() -> Int?
    capitalizedString -> String
    lowercaseString -> String
    uppercaseString -> String
    join (Array) -> String
    componentsSeparatedByString(String) -> [String]

    Type Conversion

    Int(T) -> Int
    Double(T) -> Double
    CGFloat(T) -> CGFloat
    Array(String) -> [Character]
    String([Character]) -> String
    String(Int) -> String
    "\(T)" -> String


    Assertions are debugging aids to intentionally crash a program on certain conditions.

    assert(() -> Bool, String)

    When built for release, assertions are ignored completely.

    The lecture and its slides are available via iTunes named “4. More Swift and Foundation Frameworks”.


Leave a Reply

Your email address will not be published.