Swift - the future of iOS app development
Transcript of Swift - the future of iOS app development
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)!"
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
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