deep dive into swift

126
Deep Dive Into Swift

Upload: sarath-c

Post on 15-Jul-2015

575 views

Category:

Technology


2 download

TRANSCRIPT

Deep Dive Into Swift

@saratSoftware Architect

A bit of history

Chris Lattner

• Author of the original LLVM tool chain project

• Started working on Swift in 2010

• A research intern at Microsoft Research

• Leads Development Tool Effort at Apple

Why Swift?

Modern Compilers and Optimization Techniques

Influenced by Python, Ruby, Objective-C, C#

etc.

Productivity +

Native Performance

easy to learn

Playground & REPL

Playground

REPL (Read-Eval-Print-Loop) - Write it in lldb when program runs - Use xcrun swift to run externally

Transparent interaction with Objective-C & C

can deploy to previous version of iOS and OS X

wide adoption in short time

– The RedMonk Programming Language Rankings: January 2015

“Swift has gone from our 68th ranked language during Q3 to number 22 this

quarter, a jump of 46 spots.”

Why Swift Performs better?

Smaller Runtime

generates native code

Swift Compiler Architecture

Enumerations

similar to other languages

enum CompassPoint { case North case South case East case West }

enum CompassPoint { case North case South case East case West }

var directionToHead = CompassPoint.East; directionToHead = .East;

enum CompassPoint { case North case South case East case West }

var directionToHead = CompassPoint.East; directionToHead = .East;

switch(directionToHead) { case .East: println( "Heading east") case .West: println( "Heading West") case .North: println( "Heading North") case .South: println( "Heading South") default: println("Nowhere to go") }

associated values

Enumerations can store associated values of any given type.

The type can be different for each member in the enumeration

// Associated Values Examples enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String) }

// Associated Values Examples enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String) }

var productBarcode = Barcode.UPCA(8, 85909, 51226, 3) productBarcode = .QRCode("ABCDEFGHIJ")

// Associated Values Examples enum Barcode { case UPCA(Int, Int, Int, Int) case QRCode(String) }

var productBarcode = Barcode.UPCA(8, 85909, 51226, 3) productBarcode = .QRCode("ABCDEFGHIJ")

let numberSystem = 8, manufacturer = 85909, product = 51226, check = 3

switch productBarcode { case let .UPCA(numberSystem, manufacturer, product, check) println("UPCA Detected") case let .QRCode("ABCDEFGHIJ") println("QRCode detected")

}

switch-case pattern matching

// Pattern Matching with Switch-Case let x = 9 switch(x) { case 1...5: // Closed range operator println( "Range - 1,2,3,4,5") case 6..<10: // Half closed range operator println( "Range - 6,7,8,9")

default: println("Default") }

Properties

associates values with classes, structure or

enumerations

Stored Properties store constant and

variable values

Lazy Stored Properties

• Initializes on first time access

• Declared with lazy keyword

• Lazy Stored properties can’t be a constant; for obvious reasons

• Useful when the initial values are depends on outside factors

// Lazy initialization

class DataImporter { }

class DataManager {

lazy var importer = DataImporter() var data = [String]() }

let m = DataManager() // importer has not yet been created m.data.append("Element 1"); m.data.append("Element 2"); m.data.append("Element 3");

// Initialize on first access m.importer.import();

Computed Properties computes a value (rather than store)

// Computed properties class Rectangle { var height = 0 var width = 0 var area : Int { get { return height * width } } }

Property Observers

// Property Observers class Temperature { var current : Int = 26 { willSet { println("\(newValue)"); // Prints 32 } didSet { println("\(oldValue)"); // Prints 26 } } }

var obj = Temperature() obj.current = 32;

Override properties

Closures

Self-contained blocks of functionality that can be

passed around and used in your code.

Similar to blocks in Objective-C

Closures// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort({ (a, b) -> Bool in a < b })

Closures - Trailing spaces// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort({ (a, b) -> Bool in a < b })

Closures - Parentheses// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort { (a, b) -> Bool in a < b }

Closures - Type inference// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort { (a, b) -> Bool in a < b }

Closures - Type inference// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort { a, b -> Bool in a < b }

Closures - Implicit return// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates cities.sort { a, b in a < b }

Closures - Positional Parameters

// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sort with delegates — Positional parameters cities.sort { $0 < $1 }

Closures - Operator as closure

// Closures var cities = ["New Delhi", "Trivandrum", "Kochi", "Bangalore"]

// Sounds interesting? cities.sort( < )

Optionals

represent possible missing values

stack.pop? response.parse().age?

// Age can be nil var age : Int? age = response.parse()

Unwrapping

var age : Int? age = response.parse() let x = age! // Your program would crash if you unwrap a nil value

Optional Binding

class Person { var residence : Residence? }

class Residence { var address : Address? }

class Address { var buildingNumber : String? var streetName : String? var apartmentNumber : String? }

// Optional Binding if let home = paul.residence { if let postalAddress = home.address { if let building = postalAddress.buildingNumber { // Code } } }

Optional Chaining

// Optional Chaining let buildingNumber = paul.residence?.address?.buildingNumber

// optional chaining + bind + unwrap if let buildingNumber = paul.residence?.address?.buildingNumber {

}

Initializer

Convenience & Designated Initializers

designated initializers are primary initializers of a class

a class must have at least one designated initializer

classes tend to have few designated initializers

convenience initializers are secondary; supporting initializers of a class

class Food { var name: String // Designated Initializer init(name: String) { self.name = name } // Convenience Initializer convenience init() { self.init(name: "Unnamed") } }

class Food { var name: String // Designated Initializer init(name: String) { self.name = name } // Convenience Initializer convenience init() { self.init(name: "Unnamed") } }

class Food { var name: String // Designated Initializer init(name: String) { self.name = name } // Convenience Initializer convenience init() { self.init(name: "Unnamed") } }

overriding initializers

class Vehicle { let numberOfWheels = 0 }

class Bicycle : Vehicle { override init() { super.init() numberOfWheels = 2 } }

class Car : Vehicle { override init() { super.init() numberOfWheels = 4 } }

class Vehicle { let numberOfWheels = 0 }

class Bicycle : Vehicle { override init() { super.init() numberOfWheels = 2 } }

class Car : Vehicle { override init() { super.init() numberOfWheels = 4 } }

class Vehicle { let numberOfWheels = 0 }

class Bicycle : Vehicle { override init() { super.init() numberOfWheels = 2 } }

class Car : Vehicle { override init() { super.init() numberOfWheels = 4 } }

class Vehicle { let numberOfWheels = 0 }

class Bicycle : Vehicle { override init() { super.init() numberOfWheels = 2 } }

class Car : Vehicle { override init() { super.init() numberOfWheels = 4 } }

Extensions

helps you to attach functionality data types; even to the ones you didn’t create!

// Extension as instance method extension Int { func plusOne() -> Int { return self + 1 } }

var i = 5 i.plusOne() 10.plusOne()

// Extension as instance method extension Int { func plusOne() -> Int { return self + 1 } }

var i = 5 i.plusOne() 10.plusOne()

// Extension as instance method extension Int { func plusOne() -> Int { return self + 1 } }

var i = 5 i.plusOne() 10.plusOne()

// Extension as property extension Double { var km : Double { return self*1000.0 } var m : Double { return self } var cm : Double { return self / 100.0 } var mm : Double { return self / 10000.0 } var ft : Double { return self / 3.28084 } }

let threeFeet = 3.ft // Meters let oneInch = 25.4.mm // Meters

// Extension as property extension Double { var km : Double { return self*1000.0 } var m : Double { return self } var cm : Double { return self / 100.0 } var mm : Double { return self / 10000.0 } var ft : Double { return self / 3.28084 } }

let threeFeet = 3.ft // Meters let oneInch = 25.4.mm // Meters

// Extension as property extension Double { var km : Double { return self*1000.0 } var m : Double { return self } var cm : Double { return self / 100.0 } var mm : Double { return self / 10000.0 } var ft : Double { return self / 3.28084 } }

let threeFeet = 3.ft // Meters let oneInch = 25.4.mm // Meters

// Extension as class method extension UIColor { class func chilliRed() -> UIColor { return UIColor(red: 94/255, green: 25/255, blue: 33/255, alpha: 1) } }

var chilliRed = UIColor.chilliRed()

// Extension as class method extension UIColor { class func chilliRed() -> UIColor { return UIColor(red: 94/255, green: 25/255, blue: 33/255, alpha: 1) } }

var chilliRed = UIColor.chilliRed()

// Extension as class method extension UIColor { class func chilliRed() -> UIColor { return UIColor(red: 94/255, green: 25/255, blue: 33/255, alpha: 1) } }

var chilliRed = UIColor.chilliRed()

Protocols & Delegates

Protocols are interface definitions

class ViewController: UIViewController, FBLoginViewDelegate {

}

class ViewController: UIViewController, FBLoginViewDelegate {

}

Class

class ViewController: UIViewController, FBLoginViewDelegate {

}

ProtocolClass

protocol LoginProtocol { func loginSuccessful() func loginFailed() }

class ViewController : LoginProtocol { func loginFailed() { // code } func loginSuccessful() { // code } }

protocol LoginProtocol { var someProperty : Int { get set } func loginSuccessful() func loginFailed() }

class ViewController : LoginProtocol { func loginFailed() { // code } func loginSuccessful() { // code } var someProperty : Int = 0 { willSet { // Update UI with newValue } didSet { // code } } }

protocol LoginProtocol { var someProperty : Int { get set } func loginSuccessful() func loginFailed() }

class ViewController : LoginProtocol { func loginFailed() { // code } func loginSuccessful() { // code } var someProperty : Int = 0 { willSet { // Update UI with newValue } didSet { // code } } }

protocol LoginProtocol { var someProperty : Int { get set } func loginSuccessful() func loginFailed() }

class ViewController : LoginProtocol { func loginFailed() { // code } func loginSuccessful() { // code } var someProperty : Int = 0 { willSet { // Update UI with newValue } didSet { // code } } }

protocol LoginProtocol { var someProperty : Int { get set } func loginSuccessful() func loginFailed() }

class ViewController : LoginProtocol { func loginFailed() { // code } func loginSuccessful() { // code } var someProperty : Int = 0 { willSet { // Update UI with newValue } didSet { // code } } }

Generics

func swapInt(inout a:Int, inout b:Int) { let t = a; a = b; b = t }

func swapString(inout a:String, inout b:String) { let t = a; a = b; b = t }

var a = 10, b = 20 swapInt(&a, &b)

var p = "iOS 7", q = "iOS 8" swapString(&p,&q)

func swapInt(inout a:Int, inout b:Int) { let t = a; a = b; b = t }

func swapString(inout a:String, inout b:String) { let t = a; a = b; b = t }

var a = 10, b = 20 swapInt(&a, &b)

var p = "iOS 7", q = "iOS 8" swapString(&p,&q)

// MARK: With Generics func Swap <T> (inout a: T, inout b: T) { let t = a; a = b; b = t }

Swap(&a, &b); Swap(&p, &q);

func swapInt(inout a:Int, inout b:Int) { let t = a; a = b; b = t }

func swapString(inout a:String, inout b:String) { let t = a; a = b; b = t }

var a = 10, b = 20 swapInt(&a, &b)

var p = "iOS 7", q = "iOS 8" swapString(&p,&q)

// MARK: With Generics func Swap <T> (inout a: T, inout b: T) { let t = a; a = b; b = t }

Swap(&a, &b); Swap(&p, &q);

// Generic Type struct Stack<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() } }

// Stack from somewhere class Stack<T> { }

// Extension extension Stack { func top() -> T? { return nil } }

// Type constraints func findIndex<T: Equatable>( array: [T], valueToFind: T) -> Int? { for(index, value) in enumerate(array) { if value == valueToFind { return index } } return nil }

Mutating

Structures and enumerations are value types.

By default, the properties of a value type cannot be modified from within its

instance methods.

// Immutatbility and Mutating struct Point { var x = 0.0, y = 0.0

// No change in the actual object func pointByScaling(factor: Double) -> Point { return Point(x: self.x*factor, y: self.y*factor) }

// Function modifies the object mutating func scale(factor : Double) { self.x *= factor self.y *= factor } }

// Immutatbility and Mutating struct Point { var x = 0.0, y = 0.0

// No change in the actual object func pointByScaling(factor: Double) -> Point { return Point(x: self.x*factor, y: self.y*factor) }

// Function modifies the object mutating func scale(factor : Double) { self.x *= factor self.y *= factor } }

// Immutatbility and Mutating struct Point { var x = 0.0, y = 0.0

// No change in the actual object func pointByScaling(factor: Double) -> Point { return Point(x: self.x*factor, y: self.y*factor) }

// Function modifies the object mutating func scale(factor : Double) { self.x *= factor self.y *= factor } }

Advanced Operators

struct Vector2D { var x = 0.0, y = 0.0 }

func + (left:Vector2D, right:Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) }

// Compound Operator func += (inout left:Vector2D, right:Vector2D) { left.x += right.x left.y += right.y }

var vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector vector += anotherVector

struct Vector2D { var x = 0.0, y = 0.0 }

func + (left:Vector2D, right:Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) }

// Compound Operator func += (inout left:Vector2D, right:Vector2D) { left.x += right.x left.y += right.y }

var vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector vector += anotherVector

struct Vector2D { var x = 0.0, y = 0.0 }

func + (left:Vector2D, right:Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) }

// Compound Operator func += (inout left:Vector2D, right:Vector2D) { left.x += right.x left.y += right.y }

var vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector vector += anotherVector

struct Vector2D { var x = 0.0, y = 0.0 }

func + (left:Vector2D, right:Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) }

// Compound Operator func += (inout left:Vector2D, right:Vector2D) { left.x += right.x left.y += right.y }

var vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y: 4.0) let combinedVector = vector + anotherVector vector += anotherVector

struct Vector2D { var x = 0.0, y = 0.0 }

// Custom operator - Doubling prefix operator +++ {}

prefix func +++ (inout vector: Vector2D) -> Vector2D { vector += vector return vector }

let doubled = +++vector

struct Vector2D { var x = 0.0, y = 0.0 }

// Custom operator - Doubling prefix operator +++ {}

prefix func +++ (inout vector: Vector2D) -> Vector2D { vector += vector return vector }

let doubled = +++vector

struct Vector2D { var x = 0.0, y = 0.0 }

// Custom operator - Doubling prefix operator +++ {}

prefix func +++ (inout vector: Vector2D) -> Vector2D { vector += vector return vector }

let doubled = +++vector

operators are only allowed in global

scope

Using Objective-C frameworks with Swift

Bridging Header

Demo - FacebookSDK Integration

References

• The Swift Programming Language - iBooks

• Using Swift with Objective-C and Cocoa - iBooks

• WWDC 2014 Sessions on Swift

• Developing iOS 8 Apps with Swift - iTunesU - Stanford