This is my on-going cheat sheet with useful tips for Swift. If you have never seen Swift, this might give you context in what to expect, beyond that, not sure how useful it will be. Ymmv, do lmk about about crucial features I missed to mention, please add it via comments and i can update write-up.

Must-have tools

The Swift Programming Language playground:
https://developer.apple.com/go?id=swift-tour
To create a new local playground, in Xcode 7 try File -> New -> Playground

Must reads:

Swift Programming Language Reference is my favorite. Concise, good syntax reference.
The Swift Programming Language book is the official book. A bit long/verbose but definitely useful. I read it once and use it as a reference once every 2-3 months (might be less since 2.x).

The language keywords are documented here. [An excerpt from that page, understand every keyword and the rest will be intuitive if you have programming experience].

The following keywords are reserved and can’t be used as identifiers, unless they’re escaped with backticks, as described above in Identifiers.
Keywords used in declarations: class, deinit, enum, extension, func, import, init, inout, internal, let, operator, private, protocol, public, static, struct, subscript, typealias, and var.

Keywords used in statements: break, case, continue, default, defer, do, else, fallthrough, for, guard, if, in, repeat, return, switch, where, and while.

Keywords used in expressions and types: as, catch, dynamicType, false, is, nil, rethrows, super, self, Self, throw, throws, true, try, __COLUMN__, __FILE__, __FUNCTION__, and __LINE__.

Keywords used in patterns: _.

Keywords reserved in particular contexts: associativity, convenience, dynamic, didSet, final, get, infix, indirect, lazy, left, mutating, none, nonmutating, optional, override, postfix, precedence, prefix, Protocol, required, right, set, Type, unowned, weak, and willSet. Outside the context in which they appear in the grammar, they can be used as identifiers.

The following tokens are reserved as punctuation and can’t be used as custom operators: (, ), {, }, [, ], ., ,, :, ;, =, @, #, & (as a prefix operator), ->, `, ?, and ! (as a postfix operator).  

Cheat sheet

[These are mostly aimed at C# programmers] Semicolons are not required after each statement, but you can still use them. I find it more readable to use them.

Type system

Swift has value types and reference types (classes).
If follows similar design as C# where value types are always assigned by 'copy' semantics, where reference types are actual references.
One interesting difference is that String, Array, Set and Dictionary are value types (they inherit from struct). Primitives (like Bool, double, float,Int, etc.) are all value types.

variable declarations

Beyond variable name, type declaration (which can often be inferred), Swift has two ways to declare variables based on whether the references will change:

Use var for variables that you can re-assign
Use let for constants (variables that hold a reference to something that is set once. Constants does not imply the object itself is immutable, you just can't change that reference to something else, but can update the object's members. Here are examples of declaration syntax.

var name = value; //infers type  
var name : <Type>;  
var name : <Type> = value; 

let myPerson = Person2( name: "Unknown");  
myPerson.Name = "Jaime"; // OK to alter  the state of myPerson instance  
// myPerson = Person2 ("second"); // Not OK, as this would be setting it twice and it is a 'constant' this would throw an error.. 

Classes & inheritance

  • Swift has single class inheritance.
  • You can use public, private & internal modifiers for access control. Default (when no specifier provided) is internal
  • Use override keyword when overriding methods, properties or propertyObservers.
  override func functionName () { }   
  override var propertyName: String {  return "override" + super.propertyName ; }
   var computedProperty : String { 
   get { return "some computed value" ;  } 
   set { /* use newValue if not declaring a var name for value passed in */
      placeholder = newValue; 
   } 
} 
  • Use super to refer to base class and self to refer to your instance within your instance's methods & properties
  • To prevent overrides in subclasses, use final modifier.
  • Classes can be marked as final ( similar to sealed in C#)
  • static methods are called Type methods. they have class modifier upon declarations. self refers to type within static methods.
  • constructor's name is init , destructor is deinitand it is parameterless (no parentheses in declaration). For classes, you must initialize all it's stored properties (unless they are optional) before initializer completes, or by providing a default value upon declaration.
  • in property setters, the 'implicit' value is called newValue (where in C# the name is value
  • For stored properties, Swift has a didSet and willSet on properties and they call these property Observers. These follow inheritance (e.g. willSet of super class is called when property is set in a subclass)

Enums

  • Use case keyword to introduce cases when declaring enums.
  enum Planet { case Earth, Venus, Mercury, Mars, Jupiter  }

or

enum Planet  {  
case Earth // Notice no comma here, I find it weird  
case Venus,  Mercury, Mars ... // No comma on last one  
} 
  • enum can have methods
  • enum cases can have different values associated with them. [I am still getting used to this, has been handy]
  enum ServerResponse {
  case Result (String, String) 
  case Error ( String ) 
  } 

  let success = ServerResponse.Result("6:00 am", "8:09 pm")
  let failure = ServerResponse.Error("Out of cheese.")
  • raw values for enums can be string, character, int or floating-point. the raw values are implicit when using int types, also raw values can be used to initialize an enum

Protocols

protocol is the name given to C# interfaces. Same name as objective-C.

  • Protocols can have calculated properties and methods.
  • classes, enumerations, and structures can all 'adopt' protocols
  • Swift allows for a mutating keyword when defining methods. mutating expresses that the method modifies the state of the object adopting the protocol.

functions

Like most other languages, functions are named blocks of code.

  • They are strongly typed.
    Basic syntax follows:
func Echo ( firstStatement: String , externalParameterName secondStatement : String = "appended default" ) -> String {  
/* -> is return type, it is optional for void functions */  
} 
  • When having multiple parameters, all but the first one are named parameters, you can omit the name by using _
  • functions can return tuples, or other functions, both of these are still typed
  • parameters can have default values
  • variadic parameters can be used. Use ... to declare these and use for loop to enumerate through them
  • by default parameters passed to the function are constants, if you want to avoid defining a new variable inside your function and want to assign a value to it, declare the parameter with var keyword, but know that the parameter's value change won't be reflected unless you declare parameter inout (below).

InOut parameters

variable parameters where changes inside the function can persist out of scope for function.. inout can be used with reference or value types (not a constant or a literal.. Use & to pass the parameter.

func swapTwoInts(inout a: Int, inout b: Int) {  
    let temporaryA = a
    a = b
    b = temporaryA
}
swapTwoInts(&someInt, &anotherInt)  

As far as I see, Swift does not have out only parameters (like C# does).

Closures

  • Closures are self-contained blocks of functionality that can be passed around. Same as lambdas in C#, or blocks in Objective-C.
  • They can capture values from enclosing function.
  • For practical purposes any function is a closure.
  • Closures can be declared inline.
//syntax 
{ (parameters) -> (return type ) in 
    <statements>
}; 
// e.g. 
reversed = names.sort({ (s1: String, s2: String) -> Bool in  
    return s1 > s2; 
}); 
// you can also do short hand argument names.. 
reversed = names.sort ( {$0 > $1 ;});  

If the closure does not escape a function, mark it with @noescape attribute.
Autoclosures (like expression lambdas in C#) is a closure created to wrap an expression passed as argument to a function. The syntax lets you omit braces around function.

let customerProvider = { customersInLine.removeAtIndex(0); };  
print("Now serving \(customerProvider())!");  

Extensions

Extensions add functionality to an existing type. This example extends Int to adopt a protocol.

extension Int: ExampleProtocol {  
  var simpleDescription: String {
      return "The number \(self)"
  }
  mutating func adjust() {
      self += 42
  }
}
print (7.simpleDescription);  

Type aliases

Type alias is alternate name for existing type.

typeAlias AudioSample = Uint16;  

tuples

Tuples group multiple values into simple compound value.

let http404error = (404, "Not found");  
let http404errorExpaneded :  (Int, String) = (404, "Not found");  

Optionals

[The Swift name for C# Nullables]. If no value assigned to optional at declaration, it is nil. To unwrap the optional, use !.

var responseCode : Int? = 404;  
var responseCodeExpanded : Optional<Int> = 404;  
let notUnrapped = responseCode ;  
print (notUnrapped) ; //prints "Optional (404)" since i did not unwrap it  
let unWrapped = responseCode! ;  
print (unWrapped); // prints 404  

There are also implicitly unwrapped optionals, most often declared with the ! postfix.

var responseCode : Int! = 404;  
var responseCodeExplicit : ImplicitlyUnwrapppedOptional<Int> = 404;  
print (responseCodeExplicit); //404 since it is implicitly unwrapped  

When unwrapping an optional that is nil you will get an error. You can use optional chaining to fail more gracefully. With chaining, if optional is nil, you will get nil. Chaining uses ? instead of !.

var unassignedResponseCode : Int?;  
print ( unassignedResponseCode?.value ); //nil, no error ! would have raised error  

Nil Coalescing Operator

var colorNameToUse = userDefinedColorName ?? defaultColorName;  
//is same as 
var colorNameToUse1 = (userDefinedColorName != nil) ? userDefinedColorName : defaultColorName;

Error Handling

It is like exception handling, but syntax is a little different.
It has a different 'scope', as you can have a scope that has several try expressions inside it. There is no finally, but has a handy defer (that works per scope) and serves the purpose of finalization/cleanup.

do  
{ 
    defer  { /*Swift2 does not have finally but this block of expressions will be executed as we leave the scope of the do/catch block */  
        <expressions> 
    }
    /*you can have multiple defers, they get called bottom up.. from when exception happens.. if exception is thrown before defer, then it is not called. 
Also different from finally in that it gets called prior to catch handlers  
*/ 
    defer  { 
        <expressions> 
    }
    try <expresion> 
    <statements>
    } catch <pattern> { 
    } catch <pattern> where <condition> {  
} 

Note: Swift does not unwind the stack on exceptions (making throws not much more expensive than a return)

Not exception related, but still error handling specific: Assertions in Swift do not execute on 'Release' builds.

Generics

  • You can make generic functions, classes, enumerations and structures.
  • Use where to specify requirements (such as protocol or class inheritance)
struct Stack<Element> {  
    var items = [Element]()
    mutating func push(item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}

Generic types can be extended. When you extend these, you don't provide the parameter type list.

extension Stack {  
    var topItem: Element? {
        return items.isEmpty ? nil : items[items.count - 1]
    }
}

You can use type constraints on the generic type, and can use where clause.

func allItemsMatch<  
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, _ anotherContainer: C2) -> Bool { ... } 

Type checking and casting

  • Use is to check whether an instance is of a certain type.
  • Use as to downcast. You can use as? and as! Swift has two special type aliases
  • AnyObjectrepresents an instance of any class type.
  • Any represents an instance of any type at all.. including functions..

[Don't overuse Any or AnyObject, use them mostly to deal w/ Objective-C interop]

Range operators

Swift has closed range and half-open range operator.

  • Closed range ( start...end )runs from start to end, including start and end.
  • Open range ( start..<b) runs from start to end, not including end.

Control flow

Swift has the usual suspects (for, while) .. but adds a few syntax tweaks..

for  index in 1...5 {  /*notice no parentheses. if you don't need index, use _ */  
} 

while and repeat-while looks like this

while index in < 5 {  /*no parentheses */  
} 

repeat  
{ 
} while condition   

there is also if and switch of course.

switch value {  
case value1:  
 statements
default:  
statements 

repeat  
{ 
} while condition   
  • switch statements must be exhaustive (all possible values covered) or have a default. The default case must appear last.
  • switch does not fall through by default. break is not required, but it can be used. To get fallthrough you can use fallthrough keyword.
  • switch cases can have where constraints

All of the control flow have transfer statements:

  • continue jumps to beginning of next iteration within a loop
  • break ends execution within loop (or case )
  • fallthrough used for switch, just continues execution to next case. Must be last line in a case

Swift also has a guard statement. it is like an if+else statement (always has an else) and syntax for if is inlined

guard let name = person["name"]  else {  return ; }  
print ("Hello \(name)" );  

Thought not quite a control-flow statement, the #available condition is usually coupled w/ control flow.. so mentioning it here..

if #available (iOS 9, OSX 10.10, *)  {  
/* syntax is platform + version, platform is iOs, OSX, watchOs, the * is for everything else */ 
} 
else {  
} 

Debugging

So far debugging does not seem much different (it might be that i am not abusing the language, yet).
I did watch the WWDC 2014 Swift debugging talk, but there was little new stuff, it felt like a "look lldb does all these automatically" session. Among the things lldb does are expanding dynamic types, and unwrapping optionals. The tips I wrote down were:

  • Use fr v -R <variable> //to show raw variables
  • Use fr v -d <variable> //shows dynamic type of variable
  • don't be surprised by generic types looking like $swift.type.*
  • when using mixed debugging and expressions, it works most of the time, but you can do a few things like forcing language to evaluate (using expr -l to force the language syntax to evaluate, where language= ); for example, to force evaluation of NSString in C#, you can use expr -l objc -O -- (id)<addressofNSStringInstance> where the address usually comes from po NSStringInstance
  • using Swift REPL within in lldb -- just type repl and then get an environment to evaluate expressions, add functions, etc.

Lots more...

There is lots, lots more. These are my frequent ones. If there are any very popular ones that i missed, please leave a comment, as this will be a living document over time.
Some of the ones I did not include:

  • Working with float types (swift defaults everything to double). I feel I have not cracked this :(
  • designated, convenience and bailable initializers
  • ARC in Swift probably deserves a full post.. look for weak and unowned interim.