Swift - the future of iOS app development

50
SWIFT

Transcript of Swift - the future of iOS app development

SWIFT

Introductiono Introduced at Apple’s 2014 Worldwide Developer ConferenceoChris Lattner (LLVM, Clang)oCurrent version 2.0oOpen source programming languageoObjective-C, Rust, Haskell, Ruby, Python, C#, CLU…oCompiled Programming Language

Why?• Swift is easier to read• Swift is easier tomaintain• Swift is safer• Swift requires less code• Swift is faster• Swift supports dynamic libraries• Swift Playgrounds encourages interactive coding• Swift is a future you can influence

DIFFERENCES• Header Files• Brackets/Semicolons• Ease of use• Shorter syntax• Clean classes

// objective c#import "ViewController.h”@implementationViewController // methods@end

//SwiftclassViewController:UIViewController {// properties andmethods!}

• Amount of code

// ObjectiveC@property (strong, nonatomic) IBOutlet UITextField *input;@property (strong, nonatomic) IBOutlet UILabel *label;[self.label setText:[NSString stringWithFormat:@"Welcome,%@", self.input.text]];

//Swift@IBOutlet var input:UITextField!@IBOutlet var label: UILabel!label.text = "Welcome, \(input.text)!"

CONSTANTS&VARIABLES

TYPE INFERENCE

let constant = 1 // readonly, cannot be re-assignedconstant = 2// ERROR !!!

var variable = 1 // readwrite, can be re-assignedvariable = 2 // OK

// Type inference multiple variablesvar variable1 = 1 , variable2 = 2, variable3 =3

- 'let' over 'var', when possible

TYPE ANNOTATIONSlet constant = 1let constant: Int = 1 // no need for : Int

var variable: Intvariable = 1

// Type annotations multiple variablesvar double1, double2, double3: Double

• UNICODECHARACTERS IN CONSTANT&VARIABLENAMES

TYPEALIASES• DEFINEANALTERNATIVENAME FORANEXISTINGTYPEtypealias SmallIntAlias =UInt16

• typedef double NSTimeInterval;

NUMBERSINT,UINT, FLOAT&DOUBLE

varmagic: Int = 42 // decimallet pi:Double = 3.14 // 64-bit (default)let pi: Float = 3.14 // 32-bit

• BOOLEANTRUE& FALSE

TUPLESLIGHTWEIGHT, TEMPORARYCONTAINERS FORMULTIPLEVALUES

let myTuple= (1.0, -2.0) // CompoundType: (Double, Double)

let first=myTuple.0let second=myTuple.1

OPTIONALSANOPTIONALVALUEEITHERCONTAINSAVALUEORNIL

var optionalInt: Int? = 42optionalInt = nil // to indicate that the value is missingvar optionalDouble: Double? // automatically sets to nil

// Check if niloptionalDouble == niloptionalDouble != nil

if newName != nil {!print("His name is \(newName!)")!}

OPERATORS• //ModuloOperator3% 2 // 1

• // Increment andDecrement Operatori++; ++i; i--; --i

• // CompoundAssignment Operatori += 1 // i = i + 1

• // Logical Operatora || b&& c // equivalent to a || (b && c)

// Ternary Conditional Operator(a == b ? 1 /* if true */ : 0 /* if false */)

• // Nil CoalescingOperatora ?? b // a != nil ? a! : b

• // Closed RangeOperator0... 2 // 0, 1, 2

• // Half Open RangeOperator0..<2 // 0, 1

LOOPSFOR [IN]

// old school c-style for loopfor var index =0; index < 2; index++ { /* use index */ }

// new iterator-style for-in loopfor value in 0..<2 { /* use value */ }

[DO] WHILE

// while evaluates its expression at the top of the loopwhile x > 2 { /* */ }

// do-while evaluates its expression at the bottom of the loopdo { /* executed at least once */ } while x > 2

CONDITIONALSIF-ELSE

let temperature = 40

var feverish: Bool

if temperature > 37 {feverish = true} else {feverish = false}

SWITCH

switch x { // break by default

case value1:/* ... */

case value2, value3:fallthrough // to not breakdefault:/* ... */} //

• SWITCHRANGEMATCHINGswitch count {case 0:/* ... */case 1 ... 9:/* ... */default:/* ... */}

• SWITCHTUPLEMATCHINGswitch point {case (0, 0):/* ... */case (_, 0):/* ... */case (let x, 1 ): // value binding/* use x value */default:/* ... */}

• Supoorts stringmatching

PARENTHESES&BRACES(Parentheses) are optional and by convention are often omitted

{Braces} are always required, even in one statement only

if temperature > 37 { feverish = true } // OKif (temperature > 37) { feverish = true } // OKif (temperature > 37) feverish = true // ERROR !!!

FUNCTIONS• FIRST-CLASS FUNCTION▸ assign a function to variable▸pass function as argument to another function▸ return a function from a function

DECLARATION&CALL• // With parameters and return valuefunc foo(parameter1: Type1, parameter1: Type2) -> ReturnType { /*function body */ }

• foo(argument1, argument2) // call

• // Without parameters and return valuefunc bar() -> Void { /* function body */ }func baz() -> () { /* function body */ }func quz() { /* function body */ }quz() // call

EXTERNAL, LOCAL&DEFAULTPARAMETERS

// external and local parameter names

func foo(externalParameterName localParameterName: Type){

/* body use localParameterName */}

foo(externalParameterName: argument) // callmust use externalParameterNamelabel

// # = shorthand for external parameter namesfunc bar(#parameterName: Type) { /* body use parameterName */ }

bar(parameterName: argument) // call must use parameterName label

• // default parameter valuesfunc baz(parameter1: Type1, parameterWithDefault: Int =42) { /* ... */ }baz(argument1) // call can omit value forparameterWithDefault

• Closures are blocks of functionality that can be passed around

func addTwoInts(a: Int, b: Int) -> Int {return a+ b

}

func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {println("Result: \(mathFunction(a, b))")

}printMathResult(addTwoInts, 3, 5)

ENUMERATIONS• ANENUMERATIONDEFINESACOMMON TYPEFORAGROUPOF ITEMS

enumCellState {caseAlivecaseDeadcaseError}

let state1 =CellState.Alive;let state2 :CellState = .Dead

switch state1 {case .Alive:/* ... */case .Dead:/* ... */default:/* ... */}

AN ENUMERATION ITEM CANHAVE AN ASSOCIATED VALUE

enum CellState {caseAlivecaseDeadcaseError(Int) // associated value can also be a tuple of values}

let errorState = CellState.Error(-1 );

// extract associated value as constant or variableswitch errorState {case .Alive:/* ... */case .Dead:/* ... */case .Error(let errorCode): // ==case let .Error(errorCode)):/* use errorCode */}

• ANENUMERATION ITEMCANHAVEARAWVALUEenumCellState {case Alive = 1case Dead = 2case Error = 3}enumCellState: Int { // Specify the ItemRawValue Typecase Alive = 1 , Dead, Error // Int auto-increment}let stateValue =CellState.Error.rawValue // 3let aliveState: CellState? =CellState(rawValue: 1 ) //CellState.Alive

STRUCTURES• COPYVALUEONASSIGNMENTORWHENPASSED INTOFUNCTION// Structures are value typesstruct CellPoint {var x = 0.0var y = 0.0}// Structures are always copied when they are passed aroundvar a =CellPoint(x: 1.0, y: 2.0); var b = a; b.x = 3.0;a.x // 1.0 - a not changed

• MANYSWIFTLIBRARY'S BASE TYPESARESTRUCTURES▸String▸Character▸Array▸Dictionary

STRINGS & CHARACTERS// String Declarationvar emptyString = "" // == var emptyString = String()emptyString.isEmpty // truelet constString = "Hello"

// Character Declarationvar character: Character = "p"for character in "Hello" { // "H", "e", "l", "l", "o" }

// String Interpolationlet multiplier = 2let message = "\(multiplier) times 2.5 is \(Double(multiplier) *2.5)"

// Print a message in the std outputprintln(message)

// Comparing Stringslet str1 = "Hello"; let str2 = "Hello";str1 == str2 // truestr1.hasPrefix("Hel") // truestr2.hasSuffix("llo") // true

ARRAYS// ArrayDeclarationvar emptyArray = [Int]() // Array<Int>()var emptyArray : [Int] = []var array = [25, 20, 16]

// ArrayAccess: subscript out of bounds generate crasharray[1 ] // 20array[1000] // RUNTIMEERROR !!!array. count // 3array.isEmpty // false

// Array Iterationfor value in array { /* use value */ }for (index, value) in enumerate(array) { /* use index and value */ }

VARIABLEARRAYSvar variableArray = ["A"]

variableArray[0] = "A" // ["A"]

variableArray.append("B"); // ["A", "B"]

variableArray += ["C", "D"] // ["A", "B", "C", "D"]

variableArray.insert("Z", atIndex: 4) // ["A", "B", "C", "D", "Z”]

CONSTANTARRAYSlet constantArray = ["A"]

constantArray = ["X"] // ERROR !!!

constantArray[0] = "Y" // ERROR !!!

constantArray.append("B"); // ERROR !!!

constantArray.removeAtIndex(0) // ERROR !!!

DICTIONARIES// DictionaryDeclaration

var emptyDictionary = [String, Int]() // Dictionary<String, Int>()var emptyDictionary : [String, Int] = [:] // key : valuevar dictionary = ["First" : 25, "Second" : 20, "Third" : 16]

// DictionaryAccess: subscript return Optional

let second: Int? = dictionary["Second"] // .Some(20)let last: Int? = dictionary["Last"] // nildictionary. count // 3dictionary.isEmpty // false

// Dictionary Iteration

for (key, value) in dictionary { /* use key andvalue */ }dictionary.keys // [String]dictionary.values // [Int]

VARIABLEDICTIONARIESvar variableDictionary = ["First" : 25]

variableDictionary = ["Second" : 20] // ["Second" : 20]

variableDictionary["Third"] = 16 // ["Second" : 20, "Third" : 16]

let oldKeyValue = variableDictionary.updateValue(18, forKey:"Second”)

// oldValue => 20 // ["Second" : 18, "Third" : 16]

// removes keyvariableDictionary["Second"] = nil // ["Third" : 16]

CONSTANTDICTIONARIESlet constantDictionary = ["First" : 25, "Second" : 20, "Third" : 16]

constantDictionary = ["Last" : 0] // ERROR !!!

constantDictionary["Third"] = 15 // ERROR !!!

constantDictionary["Forth"] = 21 // ERROR !!!

constantDictionary["First"] = nil // ERROR !!!

CLASSESCOPYREFERENCEONASSIGNMENTORWHENPASSED INTOFUNCTION

//Classes are reference typesclass Person {var name: String?var age: Int = 0

}

// Class reference (not object) are copiedwhen they are passed aroundvar giuseppe = Person()let joseph = giuseppejoseph.name = "Joseph"giuseppe.name // "Joseph”

INHERITANCEAVAILABLEONLY FORCLASSES

// class Subclass: Superclass

classCar: Vehicle {

// override propertyoverride var formattedName: String {return "[car] " + name}

// overridemethodoverride func order() {// can call super.order()}

}

FINAL CLASSES, PROPERTIES &METHODS

// Final class cannot be subclassedfinal class Car : Vehicle { /* ... */ }class Jeep : Car // ERROR !!!class Bicycle : Vehicle {

// final property cannot be overriddenfinal var chainLength: Double

// final method cannot be overriddenfinal func pedal() { /* ... */ }}

INITIALIZATIONSETTINGINITIALVALUES FOR STOREDPROPERTIES

classCar {

letmodel: Stringletwheels = 4

init() {model = "Supercar"}

}

// Initializers are called to create a new instance of a particular type with Type() syntax

let car = Car()car.model // "Supercar”

• INITIALIZATION PARAMETERS

class Car {

let model: String

init(model: String) {self.model = model}}

// Initializers are called with external parameterslet car = Car(model: "Golf")car.model // "Golf"

DEFAULT INITIALIZER// Default Initializer are provided for classwith no superclass orstructure

class Car {var model = "Supercar"let wheels = 4}

let car =Car()car.model // "Supercar"

EXTENSIONSAVAILABLEFORENUMERATIONS, STRUCTURES&CLASSESEXTENSIONSCAN EXTENDALSOSWIFT LIBRARYTYPES

SIMILARTOCATEGORIES

PROTOCOLSAVAILABLEFOR ENUMERATIONS, STRUCTURES & CLASSES

DELEGATION

protocolGameDelegate {funcdidPlay(game:Game)}

classGame {

var delegate: GameDelegate? // Optional delegate

funcplay() {/* play */delegate?.didPlay(self) // use Optional Chaining}

}

PROTOCOLINHERITANCE// A protocol can inherit one or more other protocols// and can add further requirements on top of the requirements it inherits

protocolBaseProtocol { func foo() }

protocolAnotherProtocol { func bar() }

// InheritingProtocol requires functions: foo, bar and baz

protocol InheritingProtocol: BaseProtocol,AnotherProtocol { func baz () }

classSomeClass: InheritingProtocol {func foo() { /* ... */ }func bar() { /* ... */ }func baz() { /* ... */ }}

ANYOBJECT

// AnyObject: any object of a class typelet instance: AnyObject =Car()let car: Car = x as Car

let cars: [AnyObject] = [Car(), Car(), Car()] // see NSArrayfor car in cars as [Car] { /* use car: Car */ }

GENERICSFUNCTIONSTYPES CANBEGENERIC

▸Generics avoid duplication and expresses its intent in the abstract▸Much of the Swift Library is built with generics (Array,Dictionary)▸Type information is available at runtime

FinalWords• Same layout• Swift is future• Swift is still growing.(Not complete final product)• Complexity inAPI not in languagewe use• ObjectiveC interoperability

Thank You