Swift 2.0 Essential Training notes


Playground supports markup
  //: Playground - noun: a place where people can play

import AppKit for osx
import UIKit for ios

source files in sources folder will be compiled once
image files in resources file will make those resources available to your playground

each page has its own sources and resources files

previous and next links allows us to go back and forth between pages

markup allows us to create links between pages.

semicolons are optional in swift.
  do not put them into the code.
  only time to use is when you have two statements on a single line

0..<64 means 0 to 64

NSLog still works. Good to use if you want a timestamp in your console

veratic function can take multiple parameters

print() default separator and terminator can be found in function definition

show graph of function by clicking on Show Result button in the result side bar

"//TODO:" inserts a bolded label in the jump bar

LITERAL EXPRESSIONS:

func printLiteralExpressions() {

	print("Function: \(__FUNCTION__)")
	print("Function: \(__FILE__)")
	print("Function: \(__LINE__)")
	print("Function: \(__COLUMN__)")
}
/**
prints:
  Function: printLiteralExpresions()\n // name of this function
  File<EXPR>\n // does not work in named playground file but works in all source files
  Line7\n // line in source file
  Column:20\n // column in source file

Literal expressions are preceeded and succeeded by __ (2 underscores)

COMMENTS:

Create landmarks in swift playgrounds with the following one line comments:

// MARK: This is viewable in the jump bar
// MARK: - Add separator above this line
// TODO: Do this
// FIXME: Fix this

MARKUP: (make sure "render demarcation" is enabled in the right gutter )

## Header
### Header
> Block quote
* list item 1
* list item 2
1. List item 1
2. List item 2
**bold**
_italicize_
`code format`
quick help comments
/// A quick help comment
/**
Quick help multiline comment
- seealso: `someComplexFunction` // allows to embed link to function in playground
*/

REPL

type swift in command line
press return
use up and down to shuffle through history
#> means waiting for input
#. means waiting for more input
Press tab for autocompletion in terminal
:q to quit
REPL can be started in the middle of a paused xcode app
  just type repl in console

DOT NOTATION

use . notation to access property of class
use same . notation to set the property of a class
can chain multi dot notation
Good to cut up long dot notation like so:
foo
  .bar
  .bass
  .print() // works because when compiler encounters . on line, looks for line above for reference

VARIABLES AND CONSTANTS:

Swift has 2 types of values
  Value types (passed by copy)
    Structures
	    Integers
	    Floating points
	    Booleans
	    Characters
	    Strings
	    Arrays
	    Dictionaries
	    Tuples // forgetting what these are
	  Enumerations
	    Optionals // any datatype may have a value or be nil
  Reference types (passed by reference)
    Classes
    Functions
    **Closures // really want to focus on closures

Value types are passed by copy
  variable
  passed to a function
  changes to copy will not affect original
  value types are not copied until they are changed (implementation detail)
Reference types are passed by reference
  Uses a pointer to a reference
  Both pointing to the same exact instance

Variables are mutable (var)
Constants are immutable and cannot be changed (let)

Always create as constant if you don't need to change it later

Swift is a strongly typed language
Compiler will infer type of instance based on what is being assigned to it.

All types in swift should begin with capital
Variables and constants should begin wtih lowercase letter
Camel casing should be used to distinguish multiword types and instance names
Variable names and characters can be used with unicode and emojis!

Equivalent ways to explicitly state what kind of data type it is:

let aCharacter : Character = "a"
let bCharacter = "b" as Character // as operator literally casts the previous character

Write unicode scalars with \u <unicode value>
  let uWithUmlaut: Character = "\u{75}\u{308}"

When defining ints, use underscores to denote placement for easy reading
  1000000 can be written as 1_000_000
When writing an unsigned int:
  let anUnsignedInteger : UInt = 1_234_567

Float - 6 decimal precision
Double - 15 decimal place precision
  Use Double as default is recommendation from apple

Booleans are defined with true and false
  explicitly define your bools with let bool : Boolean = true

DEFINING NUMERIC LITERALS:

let binaryTen = 0b1010 // 0b
let octalTen = 0o12 // 0o
let hexTen = 0xA // 0x
let twelveMillion = 1.2e7 // 1.2 * 10^7

DEFINING TYPE ALIASES // option click to see what type it is aliasing

typealias IPOctet = UInt8 // use alias to lessen typing
  alias keyword followed by original word
let minOctetValue = IPOctet.min
let maxOctetValue = IPOctet.max

Type must be explictly declared when a value is not assigned on declaration

Constants accessed before defining value, will error.

Optionals allow us to declare
  suffix with a ?
    contains some value or nil
    nil is a valueless state
    empty string is not same as nil

Optional type is a box
  access a value we know has a string, must unwrap it.
  force unwrapping is used by following optional with !
  keeps your code as safe as possible.
  run time error will be cause if it is used unwrapped

String instances are passed by copy

M_PI is a constant imported in Foundation

print(String(format:"The %@ with a radius of %.0f", shape, radius))

String manipulation:

let quote : String = "In the end, we only regret the chnages we didn't take."
quote.hasPrefix("In the end") // true
quote.hasSuffix("Abraham Lincon") // false
quote.uppercaseString
quote.lowercaseString
quote.characters.count
quote.startIndex
quote.endIndex

let firstCharacter = quote[quote.startIndex] // gets substring

let eigthCharacter = quote[7] // does not work, will not accept int as index here
let eigthIndex = quote.startIndex.advancedBy(7) // use advancedBy method to get index
let eightCharacter = quote[eightIndex]
let lastCharacter = quote[quote.endIndex.predecessor()] // gets the eigth index

Insert and delete string componenets:

quote.insert("!", atIndex: quote.endIndex.predecessor()) // insert character at end of string
let period = quote.removeAtIndex(quote.endIndex.predecessor()) // returns last character in string

Create range:

To and including last number
  let aRange = 1...3
  let startIndex = quote.endIndex.advanceBy(-41)
  let range = startIndex..<quote.endIndex // creates range start to last number inclusive
  quote.replaceRange(range, with: replacementString)

Escape Characters:

\n - new line
\t - tab
\ - escape \ and "
\0 - null character

Swift has 3 formal collection types:
Arrays
Dictionary
Set

Default initializer:
var testScores = [Double]()
var testScores2 = Array<Double>()

Set array with multiple values at once
var scores = [Double](count: 4, repeatedValue: 10.0)
var scores2 = Array(count: 20, repeatedValue: 0) // element types infered by repeated value

Can be inialized wtih optionals
Pick a style that works for you and stick with it.

threeStooges.isEmpty // checks if has any elements
threeStooges.contains("Moe") // returns true or false

let twoStooges = threeStooger[0..<2].sort(>) // sorts array in ascending order

Arrays passed by copy

Use + to join 2 arrays.

myArray + ["David", "Shemp"]

// Nesting arrays

Break them into separate lines to make it look good.

print(famousGroupsOfThree.flatMap( { $0 } )) // flaten multidimensional arrays
// this is a closure function
// short hand argumenting

Store values of the same type in Dictionaries.
No redundant keys are allowed.

Declare Dictionary

var birthYears : [String : Int] = [:]
var raceResults = Dictionary<Int, String>()
var tourDeFranceResults : [Int:String]

Setting a value to nil removes it from the dictionary

Get all values in array

Array(stockPrices.keys)
Array(stockPrices.values)

Modifying Dictionaries

Remove value for key returns key

You can nest dictionaries as well

Optional chaining
If any part is nil along the way to resolving the value, return nil.

Sets have a long form

var teachers = Set<String>()
var staff : Set<String> = []

When adding items to a set, any dupblicates will be removed.

Set supports count and isEmpty

.intersect
.union
.exclusiveOr
.subtract

Insert and remove values in Sets

Need to force unwrap arguments if the method does not accept an optional.

Defining Tuples

Group multiple values into a combinatorial value.

Useful to return multiple values from a function.

let httpStatus = (200, "Ok")

var playerScores: ([Int], firstName: String, lastName: String?)

Tuples can be accessed by index or by the name of the variable

**Tuples seem like a light-weight class replacement.

Add up the scores in tuples liek this:
let averageScore = scores.reduce(0, combine: +) / scores.count

Writing underscores for unneeded values can speed up compile time.

let (httpStatusCode, _) = httpStatus200

** use the letter t to switch lynda.com viewer from fullscreen to normal

Use dot notation to access nested tuples.

// Operators

Compiler will change int values to float implicitly

Division of integers will return an integer. Change one of those to a double and it will give you a decimal.

Swift modulus does floating point modulus as well!

a &+ 1
wraps around to maximum value.

Strings can use + and += to concatenate string

Arrays can use + and += to join two arrays

Instances of a class are passed by reference.

== checks for equality between operands
**=== checks if two operands are pointing to the exact same instance

Supports ternary operators ? true : false

Ternary operators can be nested like so:

let generation = birthYear < 1945 ? "Greatest Generation" : // switch statement is better than this
birthYear < 1965 ? "Baby Boomers" :
birthYear < 1982 ? "Generation X" :
birthYear < 1965 ? "Generation Y" :
"Generation Z"

**Coalescing operators
let defaultSize = "M"
var selectedSize: String?
let orderSize = selectedSize ?? defaultSize // not sure I get this one

Range operators

to but not including the ending value

let rangeA = 0..<10 // 0 through 9
let rangeB = 0...10 // equals 0 through 10 including 10

Type checking and casting operators:

Classes are reference types

class ClassB : ClassA // Class b inherits from Class A

let arrayOfClassInstances = [a, b]

item2 is ClassB // checks to see if this is an instance of the ClassB class type

// as! is a forced downcast
let classBInstance = item2 as! ClassB

// as casts a subclass as its superclass

let classBACtingAsClassAInstance = classBInstance as ClassA

[AnyObject]  // allows for any kind of class in the array
[Any] // allows for any kind of class or value in the array

Preceding zeros can be removed in a 0b00001010 binary value
rewrite as 0b1010

For loops do not need to be wrapped in paranthesis

for i in 0..<10 {
print(i)
}

for _ in 0..<3 {  // underscore used here when the variable i is not needed.
print("I will not waste chalk")
}

// Stride method allows us to iterate through a loop at different step lengths between

for i in 3.stride(to: 30, by: 3) {
print(i)
}

// print out key value pairs in an array

for (k, v) in people {
print("\(k): \(v)")
}

// iterat through values in a Set
for v in letters {
print(v)
}

// iterate through array with conditional
for n in numbers where n.isPrime {
print("\(n) is a prime number")
}

//While loops

click blue play button in playground to re-execute the playground code


if statements don't need parenthesis

// if available

if #available(iOS 9, OSX 10.11, watchOS 2.0, *) { // stars indicate a wildcard. Parens required for #available()
    
    // Use applicable API from iOS 9, OS X
    // 
} else {
    // execute other API code if those platforms are not available
}


**// Optional binding

var firstName: String? = "Betty"
if let firstName = firstName { // set as constant
    printf("Hello")
}

**// Guard statement

guard birthday.earlierDate(twentyOnesBirthday) == birthday
  else { // falls through if false
    print("\(name) is not old enough")
    continue
  }

  print("\(name) can enter")
}

values assigned in a guard statement endure for the lenght of the guard statement.

// Switch

// create switch based on 2 values

let die1 = [1, 2, 3, 4, 5, 6].randomItem()
let die2 = [1, 2, 3, 4, 5, 6].randomItem()

switch(die1, die2) {
    case (1,1):
      fallthrough
    case (6,6):
      print("30 points")
  default:
    break
}

// Using Labels // NEVER GOING TO USE THIS!!!

var i = 0
let hello = "Hello, Playground!"

start: do { // here is the label
    i++
  do {
    print(hello)
  }
  if i < 3 {
    continue start // goto label
  }
}

// Enums

Use dot notation to write out the enumeration quickly

// Defering code execution

if allSystemGO {
    defer { // runs only after the for loop completes and reaches end of if scope
      print("lift off!")
    }

    for i in (1...10).reverse() {
      print(i, terminator: " ")
    }
}

// Optional chaining

**if let marciasAge = hank.children?.first?.children?[1]. // if anything along the way is nil, whole thing is nil

//optional chain always returns an optional.

func sayGreeting(greeting: String, toName name: String) { // sets name with directive toName:
    print("\(greeting), \(name)!")
}

func addTwoIntegers(a: Int, _ b: Int) { //underscore suppresses the parameter name
    print("\(a+b)")
}

addTwoIntegers(3,5)

func addTwoIntegers(a: Int, _ b: Int) { //underscore suppresses the parameter name
    return a + b
}

let sumOfIntegers = addTwoIntegers(3,5)

// set a function name to be reused

let integerAdder = addTwoIntegers // this sets the method to this new method name

let integerAdder: (Int, Int) -> (Int) = addTwoIntegers

integerAdder(4,6)

let helloWorldSayer: () -> () = sayHelloWorld // keep in mind to keep off parens for the method itself

Void is just a type alias for an empty tuple

so it can be rewritten like this:

let helloWorldSayer2: Void -> Void = sayHelloWorld

// set methods with default parameters like this, set default parameter at end of parameter list.

func sayGreeting(greeting: String, toName name: String = "friend") { // sets with default param
    print("\(greeting), \(name)!")
}

sayGreeting("Hey") // now we can omit the name because it has a default value set on it

**veriatic parameters

**inout parameters // pass values by reference

// prefix argument with & to show that it is an inout parameter and passes by reference

// Create contextual help

/**
Mutates passed in score
- parameter score: raw score
- parameter meanScore: average score
- parameter deviation: standard deviation
*/

@available(*, introduced=1.2, depreciated=2.0, message="Use different version") // used to depricate a function

// Pass reference type parameter to function

Pass a function into another function:

func addTwoIntegers(a: Int, _ b: Int) -> Int {
  return a+b
}

func performIntegerOperation(operation: (Int, Int) -> Int, a: Int, b: Int) -> Int {
    return operation(a, b)
}

// rewritten to take a function instead of parameters

performIntegerOperation(addTwoIntegers, a: 10, b: 8) // notice we do not pass the parens, we pass the function name followed by a list of parameters

**// create nested function that returns function
  // requires returning an alias of the function that is created inside of the nested function

**// Currying

replace multiparameter fucntion with a single curried function

func addLineItem(product: String, price: Double)(quantity: Int) -> String {
    let discountMultiplier: Double
    switch quantity {

    }
    return String(format.....)
}
let sellCustomTShirt = addLineItem("Custom Tshirt", price: 10.0)
var lineItem = sellCustomTshirt(quantity: 5) // here is the result of currying the function, can call with default vars and a single param

**// Error Handling

Handling Errors

use enumerations for swift error handling.

define functions that throw errors

func performAction() throws {
  guard encounteredErrorA = false else {
    throw Error.A  // control will be moved out of the function
  }
  guard encounteredErrorB = false else {
    throw Error.B(code: randomCode, function: __FUNCTION__. 
      line: __LINE__)  // throws literal function name and line number
  }
    print("Action completed successfully")
}

do {
    try performAction() // need to call with try to a func that throws
} catch Error.A {
    print("Error: \(error)") // local error value is created by a catch clause
} catch Error.B(code, function, line) where code > 4 {
    print("Error occured in \(function) at line \(line) code" \(code)") // local error value is created by a catch clause
} catch {
    print("Something went wrong: \(error)") // catch all statement here
}

Overloading Function // same name, different inputs
  can coexist when they have different parameters
  can coexist when they have return types parameters
  
Create custom operators
  Start wtih ascii characters or unicode calendars
  Must be declared globally

infix operator <==> { precendence 130 associativity left}

func <==> (left: CGPoint, right: CGPoint) -> Bool {
    return left.x == right.x && left.y == right.y
}

pointA <==> pointB

****Closures // supports so many varieties of a closure!

Functions in swift are actually a type of closure
  Can be coded inline, blocks, lambdas, or anonymous functions
var names = ["David", "Jenny", "Mock", "Pie"]
let sName = names.filter({ (name: String) -> Bool in 
    return name.lowercaseString.characters.first! == "s"
})
let sName2 = names.filter {
    $0.lowercaseString.characters.first! == "s"
}
let reversedSortedName = names.sort { $0 > $1} 
reverseSortedName

Author: David Neely

Professional Software Developer. Technology and Web Coordinator at the University of Hawaii's Manoa Career Center.