3. Swift
• New programming language introduced by
Apple on June 2014 at WWDC
• Builds on the best of C and Objective-C, without
the constraints of C compatibility
• Development started by Chris Lattner, who also
started the LLVM and Clang project
4. Swift
• Safe programming patterns and modern
features
• Seamless access to all existing Cocoa
frameworks
• Mix-and-match interoperability with Objective-C
9. Variables & Constants
• Defined using var or let keyword
• No need to define type
• Swift can mostly infer the type
• Can contain any unicode character
var instrument: String = “guitar”
let nrOfSongs = 42
var trackLength = 3.23
10. Strings
• Collection of characters that can be accessed easily
• Seamlessly bridged: NSString API available
• Mutability defined by assignment (var or let)
• String interpolation for literals, variables and expressions
let instrument = “guitar"
!
let music = "play (instrument)"
let noise = "play " + instrument
11. Numbers
• Integers are stored as Int or UInt
• can be written as decimal, binary, octal, hexadecimal
• have max and min properties: Int.max
• Floating point numbers are stored as Float and Double
• can be written as decimal and hexadecimal
• Can contain underscores for readability: 7_777.77
• Bool can be true or false
12. Arrays
• Stores ordered list of multiple values
• Arrays are type specific
• Accessed using properties, methods or subscripting
var numbers: Array<Int> = Array<Int>()
var numbers: [Int] = [Int]()
!
numbers = [1,2,3]
numbers = [Int](count:7,repeatedValue:0]
13. Dictionaries
• Containers that store multiple key-value pairs of the
same type
• Accessed using properties, methods or subscripting
• Assigning nil as a value removes it
var numbers:Dictionary<Int,String> = Dictionary<Int,String>()
!
numbers = [1:“One”,2:“Two”,3:”Three”]
14. Tuples
• Group multiple values of any type into a single compound value
• Values can be of any type
• Values can be accessed by index
• Tuples can have named values
let instrument = ("guitar", “strings")
println(instrument.0)
!
let (name, family) = instrument
!
let instrument = (name: "guitar", family: "strings")
15. Loops
• for-in loop to iterate using range
• for-in loops to iterate over a collection
• while / do-while loops if unknown number of iterations
for ix in 1…5 { . . . }
for var ix = 0; ix < 7; ix++ { . . . }
for (key, value) in aDictionary { . . . }
!
while ix < 7 { . . . }
do { . . . } while ix < 7
16. Conditionals
• if / else for simple conditions
• switch statements for complex conditions
if number == 5 { . . . }
!
switch number {
case 5:
println(“5”)
default:
println(“default”)
}
17. Conditionals - Switch
• do not fall through (no break needed)
• must be exhaustive (use default:)
• support ranges: case 0…7:
• support tuples: case (1, 2):
• value binding: case (let x, 2):
• can use where clause to check additional conditions
case (let x, let y) where x == y:
18. Control Transfer Statements
• continue
• break
• return
• fallthrough
• loops and switches can be labeled to be used with break and continue
counter: for i in 1...7 {
for j in 1...7 {
println("(i) - (j)")
if i == 3 { continue counter}
}
}
20. Optionals
• Used where a value might be missing by adding a ? sign
• Similar to nil in Objective-C, but can be used on any type
• non optionals can not be nil
• Optionals can implicitly be unwrapped by adding a ! sign (forced
unwrapping)
let instruments = ["guitar" : 6, "bass": 4, “ukulele”: “8”]
let nrOfStrings: Int? = instruments[“guitar"]
!
if nrOfStrings != nil {
println(nrOfStrings!)
} else { . . . }
21. Optionals
• Use optional binding to find out if an optional
contains a value
let instruments = ["guitar" : 6, "bass": 4, “ukulele”: “8”]
let nrOfStrings: Int? = instruments[“guitar"]
!
if let nrOfStrings = instruments["guitar"] {
println(nrOfStrings)
} else { . . . }
• Use optional chaining when a value might be nil
let familyName = guitar.family?.name?
23. Functions
• Functions are blocks of code that execute a specific task
• Functions have parameters and can return values - default to void
• Parameters can have default values
• They should always be placed at the end of the list
func play(instrument: String = "guitar") -> String {
return "play (instrument)"
}
!
play(instrument: "drums")
24. Functions
• Parameter names are not required when calling a function
that has no default values
• Functions can return multiple values using tuples
• Use # if external and internal parameter names are the same
func play(instrument: String) -> (String, volume: Int) {
return ("play (instrument)", 7)
}
play(“guitar").volume
!
func play(instrument instr: String) -> String { . . . }
func play(#instrument: String) -> String { . . . }
25. Functions
• Functions can take a variable number of
arguments using variadic parameters
• One function can only have one variadic
parameter
func playInstruments(instruments: String...) -> String {
var play = "playing "
for instrument in instruments {
play += instrument + " "
}
return play
}
playInstruments("guitar", "drums", "sax")
26. Functions
• Parameters are constants by default and can not be changed
• They can be defined as variables using var
• Variables parameters can only be modified within a function
• To persist a variable outside a function the inout parameter is needed
func swapTwoInts(inout a: Int, inout b: Int) {
let tmpA = a
a = b
b = tmpA
}
var x = 3, y = 7
swapTwoInts(&x, &y)
27. Functions
• Functions have a specific function type that can be assigned to
variables
• They can be passed as parameters and returned by other
functions
• Functions can be nested
func iPlay(player:(String) ->String, song:String) ->String {
return player(song)
}
func playGuitar(song: String) -> String {
return "playing (song) on guitar"
}
let playing = iPlay(playGuitar, "I sat by the ocean")
29. Closures
• Closures are self-contained blocks of code that
can be passed around
• Functions are named closures!
• Closures can capture and store references and
constants from their surrounding context
• Trailing closures can be used for readability
• Closures start using the in keyword
30. Closures - Example
let playMusic = { println("make some noise”) }
!
!
!
func repeat(count:Int, song:String, player:(String)->(String)) {
for i in 0..<count {
println(player(song));
}
}
repeat(5, "Even Flow") {
(song: String) -> String in
return "playing (song)"
}
32. Classes
• Classes are program code templates for creating
objects, consisting of properties and methods
• No need for interface/header files
• No need to inherit from any other class
• No abstract class support
• Compare using the identity operator ===
33. Classes - Properties
• Access to properties handled automatically
• Properties do not have a corresponding instance
variable
• Every property needs to have a value assigned
• Properties without a setter are read-only
• Can have lazy stored properties (lazy)
• Type properties are defined using class keyword
34. Classes - Example
class Instrument {
let type: String
var isUsed: Bool = false
init(type: String) {
self.type = type
}
var info: String {
get {
return isUsed ? "used (type)" : "new (type)"
}
}
}
!
let electricGuitar = Instrument(type: "guitar")
35. Classes - Properties
• Property observers can respond to changes in a
properties’ value (willSet & didSet)
var isUsed: Bool = false {
willSet(willBeUsed) {
let msg = (self.isUsed ? "was" : "was not") +
" used and “ +
(willBeUsed ? "is used now" : "is not used now”)
println(msg)
}
}
36. Classes - Methods
• Methods are functions associated with a particular type
• Subscripts are special methods (subscript) for
accessing members. They can contain any number of
input parameters of any type.
class Instrument {
func play() {
println("make some noise")
}
subscript(ix: Int) -> String {
return "model (ix)"
}
}
37. Initialization
• The class needs to be completely initialized before
accessing any property or method
• Properties that are allowed to have no value can be
declared optional using the ? sign
• Property observers are NOT called on initialization
• Every class must have at least one designated initialiser
• Every class can have multiple convenience initializers
• Deinitializers can be used for cleaning up
38. Initializer Chaining
• Designated initializers must call a designated
initializer from their immediate superclass
• Convenience initializers must call another
initializer available in the same class
• Convenience initializers must ultimately end up
calling a designated initializer
39. Initialization - Example
class Instrument {
let type: String
var family: String?
init(type: String) {
self.type = type
}
convenience init(type: String, family: String) {
self.init(type: type)
self.family = family
}
deinit {
println("instrument (type) destroyed")
}
}
!
let guitar = Instrument(type: “guitar")
40. Initialization
• Closures can be used for initialising complex
properties
class Some {
let some: String = {
return "some"
}()
}
41. Inheritance
• Classes can inherit methods, properties from other
classes
• Initializers are not inherited by default
• Initialize own class properties before calling super.init
• Overridden methods need override keyword
• Methods marked as final can not be overridden
• An entire class can be marked as final
42. Inheritance - Example
class Guitar : Instrument {
init() {
super.init(type: "guitar")
family = "Strings"
}
!
override func play() {
println("make some noise")
}
}
!
let guitar = Guitar()
44. Structures
• Structures are value types, they are always
copied, not referenced
• Structures can have initializers, methods and
properties
• Automatically generated memberwise initializer
• Structures do not have deinitializers
• Array and Dictionary are structures
45. Structures
• All properties of constant structures are constant as
well
• Methods for modifying structure properties need
the mutating keyword
• Structures do not support inheritance
• No type-casting
• Type properties are defined using static keyword
46. Enumerations
• An enumeration is a complete collection of items
• Enumeration values are fully-fledged in their own
• Enumerations are first-class types!
• Enumerations can have methods & initialisers
• Enumeration can have default raw values of the
same type
47. Enumerations - Example
enum Instrument: Int {
case Guitar = 1, Base
case Drums, Bongo, Trumpet, Saxophone
func description() -> String {
switch self {
case .Guitar, .Base:
return "Strings"
case .Trumpet, .Saxophone:
return "Wind"
default:
return "Unknown"
}
}
}
let instrument = Instrument.Trumpet
instrument.description()
instrument.toRaw()
let unknown = Instrument.fromRaw(1)?.description()
48. Enumerations
• Enumerations can have associated values
enum Instrument {
case Guitar(nrOfStrings: Int), Base
case Drums, Bongo
func description() -> String {
switch self {
case .Guitar(let nrOfStrings):
return ("(nrOfStrings)-string guitar")
default:
return "Unknown"
}
}
}
let instrument = Instrument.Guitar(nrOfStrings: 6)
instrument.description()
50. Extensions
• Extensions add new functionality to existing classes,
structures, … etc.
They are similar to Categories in Objective-C
• They can add methods, computed properties, initialisers
but no stored properties
extension Instrument {
func rock() {
println("(type) is rocking")
}
}
51. Protocols
• A protocol defines methods and properties a class, struct
or enumeration can or must adopt
• Existing types can be extended to adopt a protocol
• A protocol can inherit from one or more other protocols
• Protocol composition can be used to combine protocols
• Any protocol can be used as type
• Define as @objc for type checking and optional support
52. Protocols - Example
@objc protocol Instrument {
func play()
}
!
class Guitar: Instrument {
func play() {
println("playing guitar")
}
}
!
let items = [Guitar(), NSString()]
!
for item in items {
if let instrument = item as? Instrument {
instrument.play()
}
}
53. Generics
• Generic code enables writing flexible, reusable
functions and types
func swapTwoValues<T>(inout a: T, inout b: T) {
let tmpA = a
a = b
b = a
}
54. Generics
• You can define your own generic type
• and specify type constraints
struct Stack<T: Instrument> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() {
items.removeLast()
}
}
var guitarStack = Stack<Guitar>()
55. References
• WWDC 2014 Videos
• Apple Books
• The Swift Programming Language
• Using Swift with Cocoa & Objective-C
• Web
• https://developer.apple.com/swift/
57. ARC
• Swift handles memory management using
automatic reference counting
• Think about relationship between object instead
of memory
• Avoid strong reference cycles by using weak or
unowned references
58. Assertions
• Use assertions whenever a condition has the
potential to be false, but must be true
• End code execution
let age = -3
assert(age >= 0, "age can no be less than 0")