Skip to content

Instantly share code, notes, and snippets.

@Gernot
Created November 25, 2014 14:02
Show Gist options
  • Save Gernot/e47c399fb2b686924e25 to your computer and use it in GitHub Desktop.
Save Gernot/e47c399fb2b686924e25 to your computer and use it in GitHub Desktop.
Swift Workshop

[fit]Introduction

[fit]to

[fit]Swift


Gernot Poetsch

@gernot gernot@nxtbgthng.com


##What we'll do

  • Basics
  • Optionals
  • Classes, Extensions and Protocols
  • Structs, Enums
  • Memory Management? Debugging? Ask!

Play along in Playgrounds!


Mobile Development is…

[fit] 10% Programming Language

[fit] 90% Frameworks

…so today we'll concentrate on the language.


#A bit of history…

1972: C 1972: Smalltalk

1983: C++ 1983: Objective-C (2006: Obj-C 2.0)

1990: Haskell 1995: Java

2014: Swift


#[fit]Current Status

  • Swift is still in Development
  • Xcode will crash!
  • Even long-term, the language will change
  • If the language changes, your Apps will still run — but you'll have to revisit your code

Where can you use Swift?

  • Apps for OSX and iOS
  • Playgrounds
  • Command Line Tools #!/usr/bin/env xcrun swift -i
  • REPL (for debugging)

#What is Swift designed for?

  • Modern High Level Programming
  • Objective-C Compatibility
  • C Compatibility
  • LLVM Optimization

[fit]Static

[fit]Strong

[fit]Inferred

[fit]Type System


[fit]Optionals


Objective-C

NSString *name; //initialized with nil
double price; //initialized with 0
NSInteger position; //can never be nil, using NSNotFound instead
CGRect myRect; //uninitialized

Swift

let name = "Meier" //Implicit String, always initialized!
var favoriteColor: UIColor //has to be initialized! 
var price = 39.90 //Implicit Double
var position: Int? //Optional Int, initialized nil
let myRect = CGRect(x:0, y:0, width:10, height: 10)

##Working with Optionals

Unwrapping:

if position != nil {
	let newPosition = position! + 1 //implicitly an Int
}

Conditional Unwrapping:

if let myPosition = position {
	let newPosition = position + 1
}

Implicitly unwrapped optionals

var position: Int!
newPostion = position + 1 //Attention, crashes if position is nil!

Only use when you're sure what you're doing!

Objective-C bridge still has a lot of implicitely unwrapped optionals. This will change (and break your code) — use them and check them as if they are optional


##Calling Methods on Optionals

var car: Car?
//[…]
car?.drive() //Does nothing when car == nil
car!.drive() //Crashes when car == nil

//Variable names are scoped!
if let car = car {
	car.drive()
	car.brake()
	washcenter.wash(car)
}

#[fit]Functions


func sayHello() {
	println("Hello")
}

hello()

func sayHello(name: String) {
	println("Hello \(name)")
}

hello("Earthlings")

func sayHello(name: String, peace: Bool) {
	println("Hello \(name)")
	if peace println("We come in Peace")
}

hello("Earthlings", peace: true)

func sayHello(name: String, peace: Bool = true) {
	println("Hello \(name)")
	if peace println("We come in Peace")
}

hello("Earthlings")

func sayHello(salutation name: String) {
	println("Hello \(name)")
}

hello(salutation: "Earthlings")

func sayHello(salutation salutation: String) {
	println("Hello \(name)")
}

hello(salutation: "Earthlings")

func sayHello(#salutation: String) {
	println("Hello \(name)")
}

hello(salutation: "Earthlings")

func sayHello(name: String, abductCows: () -> Void) {
	println("Hello \(name)")
	abductCows()
}

hello("Earthlings", {
	//get cows
})

hello("Earthlings") {
	//get cows
}

func sayHello(name: String, abductCows: (Int) -> Int) {
    println("Hello \(name)")
    println("Abducted \(abductCows(5)) cows")
}

sayHello("Earthlings") {
    numberOfCows in
    println("About to abduct \(numberOfCows) cows")
    return 2
}

//About to abduct 5 cows
//Abducted 2 cows

//Look, Ma! Functional Programming!

typealias cowHandler = (Int) -> Int

func sayHello(name: String, abductCows: cowHandler) {
    println("Hello \(name)")
    println("Abducted \(abductCows(5)) cows")
}

let abduct: cowHandler = {
    numberOfCows in
    println("about to abduct \(numberOfCows) cows")
    return 2
}

sayHello("Earthlings", abduct)

//Just for the record 😉

typealias 🐮 = (Int) -> Int

func sayHello(name: String, abductCows: 🐮) {
    println("Hello \(name)")
    println("Abducted \(abductCows(5)) cows")
}

let abduct: 🐮 = {
    numberOfCows in
    println("about to abduct \(numberOfCows) cows")
    return 2
}

sayHello("Earthlings", abduct)

typealias cowHandler = (Int) -> Int

func sayHello(name: String, abductCows: cowHandler) {
    println("Hello \(name)")
    println("Abducted \(abductCows(5)) cows")
}

sayHello("Earthlings") {
    _ in //ignore the parameters
    println("This is a vegan UFO. We don't abduct any cows.")
    return 0
}

[fit] Classes


let maximumAllowedWarpSpeed = 0.9999 //Global Constant

class UFO {
	let maxWarpSpeed = 2.0
	var currentSpeed = 0.0
	
	func engage() {
		self.currentSpeed = maximumAllowedWarpSpeed
		//or
		currentSpeed = maximumAllowedWarpSpeed
	}
}

class UFO {
	var currentSpeed {
		get {
			return warpdrive.currentSpeed
		}
		set {
			//newValue automatically has the value to be set.
			warpdrive.currentSpeed = newValue
		}
	}
}

class UFO {
	//Only getter!
	var currentSpeed {
		get {
			return warpdrive.currentSpeed
		}
	}
}

class UFO {
	var currentSpeed { return warpdrive.currentSpeed }
}

class UFO {
	var currentSpeed {
		willSet {
			if (newValue >= 1.0) {
				println ("Prepare for Hyperspeed!")
			}
		}
		didSet {
			println("Huiiii")
		}
	}
}

##Initialiszers

let maximumAllowedWarpSpeed = 0.9999 //Global Constant

class UFO {
	
	init(maxWarpSpeed: Double) {
		self.maxWarpSpeed = maxWarpSpeed
	}

	let maxWarpSpeed: Double
}

Objects always need to be fully initialized

init() {
	//First, initialize the object
	super.init()
	//From here on, you can use self & methods 
}

##Lazy Initialisation

class TractorBeam {
}

class UFO {
	lazy var tractorBeam = TractorBeam()
}

class TractorBeam {
    init(energy: Double) {
    	//[…]
    }
}

class UFO {
    let availableEnergy = 3.45
    
    lazy var tractorBeam: TractorBeam = {
        return TractorBeam(energy: self.availableEnergy)
    }()
}

[fit] Extensions

[fit] &

[fit] Protocols


Extensions

extension UFO {

	func activateLasers() {
		//LAZERS!!
	}
}

##Protocols

protocol Destroyer {
	func activateLasers()
}

class SuperUFO: UFO, Destroyer {
	func activateLasers() {
		//LAZERS
	}
}

var myUFO: Destroyer

##Optional Protocols

protocol Destroyer {
	optional func activateLasers()
}

class SuperUFO: UFO, Destroyer {
	func activateLasers() {
		//LAZERS
	}
}

var myUFO: Destroyer
//[…]
myUFO.activateLazers?()

[fit]Structs


struct numberPlate {
    var city = "B"
    var letters = "AB"
    var numbers = 1234
    
    var description: String {
        return "\(city) - \(letters) \(numbers)"
    }
}

var numberplate1 = numberPlate() // B - AB 1234
var numberplate2 = numberplate1 // B - AB 1234
numberplate2.letters = "CD" // B - CD 1234
// numberplate1 is still B - AB 1234

[fit] Enums


enum FuelType {
    case Kerosine
    case Plutonium
}

let fuel = FuelType.Kerosine

switch fuel {
case .Kerosine:
	//[…]
case .Plutonium:
	//[…]
}

enum FuelType {
    case Kerosine
    case Plutonium
    case Spice(Int)
    
    func energy() -> Double {
    	[]
    }
}

More Info


[fit] Thanks


More Topics

  • Memory Management and ARC
  • Inheritance, Initialization & Deinitialization
  • Debugging & REPL
  • Objective-C Bridge
  • Namespacing, Frameworks and Modules
  • Runtime Features and Swift Intermediate Language
  • Generics and Functional Programming
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment