SlideShare a Scribd company logo
1 of 396
Download to read offline
© 2014 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.
#WWDC14
Intermediate Swift
Session 403
Brian Lanier Joe Groff
Developer Publications Engineer Swift Compiler Engineer
Tools
What You Will Learn
What You Will Learn
Optionals
What You Will Learn
Optionals
Memory management
What You Will Learn
Optionals
Memory management
Initialization
What You Will Learn
Optionals
Memory management
Initialization
Closures
What You Will Learn
Optionals
Memory management
Initialization
Closures
Pattern matching
Optionals
Brian Lanier
Developer Publications Engineer
String to Integer
> Enter your age:
>
!
!
!
_
String to Integer
> Enter your age:
>
!
!
!
_
let age = response.toInt()
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
34
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
thirty
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
String to Integer
> Enter your age:
>
!
let age = response.toInt()
!
wouldn't you like to know
> Enter your age:
>
!
let age = response.toInt()
String to Integer
> Enter your age:
>
!
let age = response.toInt()
String to Integer
how rude!
> Enter your age:
>
!
let age = response.toInt()
String to Integer
-1
NSNotFound
NULL
nil 0
INT_MAX
NSIntegerMax
Nil
how rude!
> Enter your age:
>
!
let age = response.toInt()
String to Integer
-1
NSNotFound
NULL
nil 0
INT_MAX
NSIntegerMax
Nil
?
how rude!
Optional Type
Optional Type
Represents possibly missing values
!
!
!
!
!
Optional Type
Represents possibly missing values
!
var optionalNumber: Int?
// default initialized to nil
!
!
!
6
Optional Type
Represents possibly missing values
!
var optionalNumber: Int?
// default initialized to nil
!
!
!
6
Optional Type
Represents possibly missing values
!
var optionalNumber: Int?
// default initialized to nil
!
optionalNumber = 6
!
! 6
Optional Type
Represents possibly missing values
!
var optionalNumber: Int?
// default initialized to nil
!
optionalNumber = 6
!
!
6
One Sentinel to Rule Them All
> Enter your age:
> thirty
!
let age = response.toInt()
// age: Int? = nil
Non-Optional Types
!
!
var myString: String = "Look, a real string!"
!
!
var myObject: MyClass = MyClass()
Non-Optional Types
Non-optional types can't be nil
!
var myString: String = nil
// compile-time error
!
var myObject: MyClass = nil
// compile-time error
Optional Return Types
func findIndexOfString(string: String, array: String[]) -> Int
!
!
!
!
!
}
{
Optional Return Types
func findIndexOfString(string: String, array: String[]) -> Int
!
!
!
!
!
}
? {
Optional Return Types
func findIndexOfString(string: String, array: String[]) -> Int? {
for (index, value) in enumerate(array) {
!
!
}
}
Optional Return Types
func findIndexOfString(string: String, array: String[]) -> Int? {
for (index, value) in enumerate(array) {
if value == string {
return index
}
}
}
Optional Return Types
func findIndexOfString(string: String, array: String[]) -> Int? {
for (index, value) in enumerate(array) {
if value == string {
return index
}
}
return nil
}
Unwrapping Optionals
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Madison", neighbors)
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Madison", neighbors)
!
if index {
println("Hello, (neighbors[index])")
} else {
println("Must've moved away")
}
Unwrapping Optionals
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index: Int? = findIndexOfString("Madison", neighbors)
!
if index {
println("Hello, (neighbors[index])")
} else {
println("Must've moved away")
}
// error: value of optional type 'Int?' not unwrapped
Unwrapping Optionals
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Madison", neighbors)
!
if index {
println("Hello, (neighbors[index!])")
} else {
println("Must've moved away")
}
Forced Unwrapping
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Madison", neighbors)
!
if index {
println("Hello, (neighbors[index!])")
} else {
println("Must've moved away")
}
Forced Unwrapping
Hello, Madison
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Reagan", neighbors)
!
!
println("Hello, (neighbors[index!])")
// runtime error!
Forced Unwrapping
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Anna", neighbors)
!
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Anna", neighbors)
!
if let indexValue = index {
println("Hello, (neighbors[indexValue])")
} else {
println("Must've moved away")
}
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Anna", neighbors)
!
if let indexValue = index { // index is of type Int?
println("Hello, (neighbors[indexValue])")
} else {
println("Must've moved away")
}
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Anna", neighbors)
!
if let indexValue = index { // indexValue is of type Int
println("Hello, (neighbors[indexValue])")
} else {
println("Must've moved away")
}
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
let index = findIndexOfString("Anna", neighbors)
!
if let indexValue = index { // indexValue is of type Int
println("Hello, (neighbors[indexValue])")
} else {
println("Must've moved away")
}
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
!
!
if let index = findIndexOfString("Anna", neighbors) {
println("Hello, (neighbors[index])") // index is of type Int
} else {
println("Must've moved away")
}
Optional Binding
Test and unwrap at the same time
!
var neighbors = ["Alex", "Anna", "Madison", "Dave"]
!
!
if let index = findIndexOfString("Anna", neighbors) {
println("Hello, (neighbors[index])") // index is of type Int
} else {
println("Must've moved away")
}
Optional Binding
Hello, Anna
Optional Binding
class Person {
var residence: Residence?
}
!
Optional Binding
class Person {
var residence: Residence?
}
!
class Residence {
var address: Address?
}
!
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
let paul = Person()
Person
residence: nil
Optional Binding
let paul = Person()
Person
residence:
Residence
address: nil
Optional Binding
let paul = Person()
Person
residence:
Residence
address:
Address
buildingNumber: nil
streetName: nil
apartmentNumber: nil
Optional Binding
let paul = Person()
Person
residence:
Residence
address:
Address
buildingNumber: "243"
streetName: "Main St."
apartmentNumber: nil
Optional Binding
var addressNumber: Int?
!
if let home = paul.residence {
!
!
!
!
!
!
}
Optional Binding
var addressNumber: Int?
!
if let home = paul.residence {
if let postalAddress = home.address {
!
!
!
!
}
}
Optional Binding
var addressNumber: Int?
!
if let home = paul.residence {
if let postalAddress = home.address {
if let building = postalAddress.buildingNumber {
!
!
}
}
}
Optional Binding
var addressNumber: Int?
!
if let home = paul.residence {
if let postalAddress = home.address {
if let building = postalAddress.buildingNumber {
if let convertedNumber = building.toInt() {
}
}
}
}
Optional Binding
var addressNumber: Int?
!
if let home = paul.residence {
if let postalAddress = home.address {
if let building = postalAddress.buildingNumber {
if let convertedNumber = building.toInt() {
addressNumber = convertedNumber
}
}
}
}
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
?
nil
Int
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
? Int
nil
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
? Int
nil
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
?
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
?
nil
Int
Optional Chaining
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
?
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
"243"
nil
Int
Optional Chaining
?
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
243
nil
Int
Int
Optional Chaining
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
?
Int
Optional Chaining
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
nil
?
Optional Chaining
243
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
Optional Chaining
Combine with optional binding to unwrap
!
Optional Chaining
Combine with optional binding to unwrap
!
if let addressNumber = paul.residence?.address?.buildingNumber?.toInt() {
addToDatabase("Paul", addressNumber)
}
enum Optional<T> {
case None
case Some(T)
}
Optionals Under the Hood
• Advanced Swift Presidio Thursday 11:30PM
Optionals
Optionals
Use optionals to safely work with possibly missing values
• Missing values are nil
• Present values are wrapped in an optional
Optionals
Use optionals to safely work with possibly missing values
• Missing values are nil
• Present values are wrapped in an optional
Unwrap an optional to access its underlying value
• Use the forced-unwrapping operator (!) only if you are sure
• Use if let optional binding to test and unwrap at the same time
Optionals
Use optionals to safely work with possibly missing values
• Missing values are nil
• Present values are wrapped in an optional
Unwrap an optional to access its underlying value
• Use the forced-unwrapping operator (!) only if you are sure
• Use if let optional binding to test and unwrap at the same time
Optional chaining (?) is a concise way to work with chained optionals
Memory Management
Joe Groff
Swift Compiler Engineer
Automatic Reference Counting
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
BowlingPin
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
BowlingPin
left
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
if count > 1 {
var right = BowlingPin()
BowlingPin
left
BowlingPin
right
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
if count > 1 {
var right = BowlingPin()
right = left
BowlingPin
left right
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
if count > 1 {
var right = BowlingPin()
right = left
} // right goes out of scope
BowlingPin
left
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
if count > 1 {
var right = BowlingPin()
right = left
} // right goes out of scope
BowlingPin
left
Automatic Reference Counting
class BowlingPin {}
func juggle(count: Int) {
var left = BowlingPin()
if count > 1 {
var right = BowlingPin()
right = left
} // right goes out of scope
} // left goes out of scope
Ownership
Ownership
class Apartment {
var tenant: Person?
}
Ownership
class Apartment {
var tenant: Person?
}
class Person {
var home: Apartment?
Ownership
class Apartment {
var tenant: Person?
}
class Person {
var home: Apartment?
func moveIn(apt: Apartment) {
self.home = apt
apt.tenant = self
}
}
Ownership
Ownership
var renters = ["Elsvette": Person()]
Person
renters
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
Person
renters
Apartment
apts
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
Person
renters
Apartment
apts
home tenant
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
Person Apartment
apts
home tenant
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
Person Apartment
apts
home tenant
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
apts[507] = nil
Person Apartment
home tenant
Ownership
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
apts[507] = nil
Person Apartment
home tenant
Weak References
class Apartment {
!
}
class Person {
!
!
func moveIn(apt: Apartment) {
self.home = apt
apt.tenant = self
}
}
var tenant: Person?
var home: Apartment?
Weak References
class Apartment {
!
}
class Person {
!
!
func moveIn(apt: Apartment) {
self.home = apt
apt.tenant = self
}
}
var tenant: Person?weak
var home: Apartment?weak
Weak References
Person
renters
Apartment
apts
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
Person
renters
Apartment
apts
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
Person
renters
Apartment
apts
home tenant
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
Person Apartment
apts
home tenant
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
Apartment
apts
tenant
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
Apartment
apts
Weak References
var renters = ["Elsvette": Person()]
var apts = [507: Apartment()]
renters["Elsvette"]!.moveIn(apts[507]!)
renters["Elsvette"] = nil
apts[507] = nil
Using Weak References
Using Weak References
Weak references are optional values
Using Weak References
Weak references are optional values
Binding the optional produces a strong reference
if let tenant = apt.tenant {
tenant.buzzIn()
}
Using Weak References
Weak references are optional values
Binding the optional produces a strong reference
if let tenant = apt.tenant {
tenant.buzzIn()
}
apt.tenant?.buzzIn()
Using Weak References
Using Weak References
Testing a weak reference alone does not produce a strong reference
if apt.tenant {
apt.tenant!.cashRentCheck()
apt.tenant!.greet()
}
Using Weak References
Testing a weak reference alone does not produce a strong reference
Chaining doesn't preserve a strong reference between method invocations
if apt.tenant {
apt.tenant!.cashRentCheck()
apt.tenant!.greet()
}
apt.tenant?.cashRentCheck()
apt.tenant?.greet()
Same-Lifetime Relationships
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
holder: Personlet
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
holder: Personlet
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
holder: Person
init(holder: Person) {
self.holder = holder
}
}
let
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
let holder: Person
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
letweak holder: Person
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
letweak holder: Person?
Same-Lifetime Relationships
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
weak holder: Personvar ?
Unowned References
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
holder: Personlet
Unowned References
class Person {
var card: CreditCard?
}
class CreditCard {
!
!
init(holder: Person) {
self.holder = holder
}
}
holder: Personletunowned
Unowned References
Unowned References
var renters = ["Elsvette": Person()]
Person
renters
Unowned References
var renters = ["Elsvette": Person()]
customers["Elsvette"]!.saveCard()
Person
renters
card
CreditCard
holder
Unowned References
var renters = ["Elsvette": Person()]
customers["Elsvette"]!.saveCard()
customers["Elsvette"] = nil
Person
card
CreditCard
holder
Unowned References
var renters = ["Elsvette": Person()]
customers["Elsvette"]!.saveCard()
customers["Elsvette"] = nil
Using Unowned References
Using Unowned References
let holder = card.holder
Using Unowned References
let holder = card.holder
card.holder.charge(2.19)
Strong, Weak, and Unowned References
Use strong references from owners to the objects they own
Strong, Weak, and Unowned References
Strong, Weak, and Unowned References
Strong, Weak, and Unowned References
Use weak references among objects with independent lifetimes
Strong, Weak, and Unowned References
Use weak references among objects with independent lifetimes
Strong, Weak, and Unowned References
Use weak references among objects with independent lifetimes
Strong, Weak, and Unowned References
Strong, Weak, and Unowned References
Use unowned references from owned objects with the same lifetime
Strong, Weak, and Unowned References
Use unowned references from owned objects with the same lifetime
Strong, Weak, and Unowned References
Use unowned references from owned objects with the same lifetime
Memory Management
Automatic, safe, predictable
Think about relationships between objects
Model ownership using strong, weak, and unowned references
Initialization
Brian Lanier
Developer Publications Engineer
!
!
Every value must be initialized before it is used
!
!
Every value must be initialized before it is used
Initialization
var message: String
!
Initialization
var message: String
!
if sessionStarted {
message = "Welcome to Intermediate Swift!"
}
!
println(message)
Initialization
var message: String
!
if sessionStarted {
message = "Welcome to Intermediate Swift!"
}
!
println(message)
// error: variable 'message' used before being initialized
Initialization
var message: String
!
if sessionStarted {
message = "Welcome to Intermediate Swift!"
} else {
message = "See you next year!"
}
!
println(message)
Initialization
var message: String
!
if sessionStarted {
message = "Welcome to Intermediate Swift!"
} else {
message = "See you next year!"
}
!
println(message)
Welcome to Intermediate Swift!
Initializers
Initializers
Initializers handle the responsibility of fully initializing an instance
Initializers
Initializers handle the responsibility of fully initializing an instance
!
init() {…}
!
Initializers
Initializers handle the responsibility of fully initializing an instance
!
init() {…}
!
let instance = MyClass()
Initializers
Initializers handle the responsibility of fully initializing an instance
!
init(
!
let instance = MyClass(
) {…}
)
Initializers
Initializers handle the responsibility of fully initializing an instance
!
init(
!
let instance = MyClass(
luckyNumber: Int, message: String ) {…}
)
Initializers
Initializers handle the responsibility of fully initializing an instance
!
init(
!
let instance = MyClass(
luckyNumber: Int, message: String
luckyNumber: 42, message: "Not today"
) {…}
)
Structure Initialization
Structure Initialization
struct Color {
let red, green, blue: Double
}
Structure Initialization
struct Color {
let red, green, blue: Double
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
}
}
Structure Initialization
struct Color {
let red, green, blue: Double
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
}
}
Structure Initialization
struct Color {
let red, green, blue: Double
init(grayScale: Double) {
green = grayScale
blue = grayScale
}
}
// error: variable 'self.red' used before being initialized
Structure Initialization
struct Color {
let red, green, blue: Double
mutating func validateColor() { ... }
init(grayScale: Double) {
red = grayScale
green = grayScale
validateColor()
blue = grayScale
}
}
Structure Initialization
struct Color {
let red, green, blue: Double
mutating func validateColor() { ... }
init(grayScale: Double) {
red = grayScale
green = grayScale
validateColor()
blue = grayScale
}
}
validateColor()
struct Color {
let red, green, blue: Double
mutating func validateColor() { ... }
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
}
}
// error: 'self' used before being initialized
Structure Initialization
validateColor()
struct Color {
let red, green, blue: Double
mutating func validateColor() { ... }
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
}
}
// error: 'self' used before being initialized
self.
Structure Initialization
Structure Initialization
struct Color {
let red, green, blue: Double
mutating func validateColor() { ... }
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
validateColor()
}
}
Memberwise Initializers
struct Color {
let red, green, blue: Double
}
Memberwise Initializers
struct Color {
let red, green, blue: Double
}
!
!
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
Default Values
struct Color {
let red = 0.0, green = 0.0, blue = 0.0
}
Default Initializer
struct Color {
let red = 0.0, green = 0.0, blue = 0.0
}
!
let black = Color()
Class Initialization
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
}
}
Class Initialization
class Car {
var paintColor: Color
init(color: Color) {
paintColor = color
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
!
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
}
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
super.init(color: color)
hasTurbo = turbo
}
} // error: property 'hasTurbo' not initialized at super.init call
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
super.init(color: color)
hasTurbo = turbo
Class Initialization
class Car {
var paintColor: Color
func fillGasTank() {...}
init(color: Color) {
paintColor = color
fillGasTank()
}
}
!
class RaceCar: Car {
var hasTurbo: Bool
override func fillGasTank() { ... }
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
}
super.init(color: color)
hasTurbo = turbo
Initializer Delegation
BaseClass
SuperClass
Class
Initializer Delegation
BaseClass
SuperClass
Class
Designated
Designated
Designated Designated
Initializer Delegation
BaseClass
SuperClass
Class
Designated
Designated
Designated Designated
Convenience Convenience
Convenience Convenience
Convenience
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
!
!
!
!
!
!
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
init(color: Color) {
self.init(color: color, turbo: true)
}
!
!
!
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
init(color: Color) {
self.init(color: color, turbo: true)
}
!
!
!
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
init(color: Color) {
self.init(color: color, turbo: true)
}
!
!
!
}
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
self.init(color: color, turbo: true)
}
!
!
!
}
init(color: Color) {
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
self.init(color: color, turbo: true)
}
!
!
!
}
convenience init(color: Color) {
Convenience Initializers
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Convenience Initializers
class RaceCar: Car {
var hasTurbo: Bool
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
!
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
!
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Initializer Inheritance
class FormulaOne: RaceCar {
let minimumWeight = 642
Initializer Inheritance
class FormulaOne: RaceCar {
let minimumWeight = 642
// inherited from RaceCar
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Initializer Inheritance
class FormulaOne: RaceCar {
let minimumWeight = 642
// inherited from RaceCar
init(color: Color, turbo: Bool) {
hasTurbo = turbo
super.init(color: color)
}
convenience init(color: Color) {
self.init(color: color, turbo: true)
}
convenience init() {
self.init(color: Color(gray: 0.4))
}
}
Initializer Inheritance
class FormulaOne: RaceCar {
let minimumWeight = 642
init(color: Color) {
super.init(color: color, turbo: false)
}
!
!
!
}
Initializer Inheritance
class FormulaOne: RaceCar {
let minimumWeight = 642
init(color: Color) {
super.init(color: color, turbo: false)
}
!
// not inherited from RaceCar
init(color: Color, turbo: Bool)
convenience init()
}
Lazy Properties
Lazy Properties
class Game {
var multiplayerManager = MultiplayerManager()
var singlePlayer: Player?
func beginGameWithPlayers(players: Player...) {
!
!
!
!
!
!
}
}
Lazy Properties
class Game {
var multiplayerManager = MultiplayerManager()
var singlePlayer: Player?
func beginGameWithPlayers(players: Player...) {
if players.count == 1 {
singlePlayer = players[0]
}
!
!
!
!
}
}
Lazy Properties
class Game {
var multiplayerManager = MultiplayerManager()
var singlePlayer: Player?
func beginGameWithPlayers(players: Player...) {
if players.count == 1 {
singlePlayer = players[0]
} else {
for player in players {
multiplayerManager.addPlayer(player)
}
}
}
}
class Game {
var singlePlayer: Player?
func beginGameWithPlayers(players: Player...) {
if players.count == 1 {
singlePlayer = players[0]
} else {
for player in players {
multiplayerManager.addPlayer(player)
}
}
}
}
var multiplayerManager = MultiplayerManager()
Lazy Properties
class Game {
var singlePlayer: Player?
func beginGameWithPlayers(players: Player...) {
if players.count == 1 {
singlePlayer = players[0]
} else {
for player in players {
multiplayerManager.addPlayer(player)
}
}
}
}
@lazy var multiplayerManager = MultiplayerManager()
Lazy Properties
Deinitialization
Deinitialization
class FileHandle {
let fileDescriptor: FileDescriptor
init(path: String) {
fileDescriptor = openFile(path)
}
!
!
!
}
Deinitialization
class FileHandle {
let fileDescriptor: FileDescriptor
init(path: String) {
fileDescriptor = openFile(path)
}
deinit {
closeFile(fileDescriptor)
}
}
Initialization
Initialization
Initialize all values before you use them
Set all stored properties first, then call super.init
Initialization
Initialize all values before you use them
Set all stored properties first, then call super.init
Designated initializers only delegate up
Convenience initializers only delegate across
Initialization
Initialize all values before you use them
Set all stored properties first, then call super.init
Designated initializers only delegate up
Convenience initializers only delegate across
Deinitializers are there… if you need them
Closures
Joe Groff
Swift Compiler Engineer
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
{
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
{(a: String, b: String) -> Bool
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
{(a: String, b: String) -> Bool in
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
{(a: String, b: String) -> Bool in
return a < b
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
return a < b
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
return a < b
})
[Babbage, Buenaventura, Pestov, Sreeram]
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
return a > b
})
Closures
[Sreeram, Pestov, Buenaventura, Babbage]
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
Closures
in{(a: String, b: String) -> Bool
})
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
Closures
[Pestov, Sreeram, Babbage, Buenaventura]
in{(a: String, b: String) -> Bool
return countElements(a) < countElements(b)
})
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
Closures
return a < b
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
Closures
return a < b
Type Inference
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
return a < b
Type Inference
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
!
clients.sort(
!
!
!
println(clients)
in{(a: String, b: String) -> Bool
})
sort
return a < b
Type Inference
struct Array<T> {
func sort(order: (T, T) -> Bool)
}
Type Inference
struct Array<String> {
func sort(order: (String, String) -> Bool)
}
Type Inference
struct Array<String> {
func sort(order: (String, String) -> Bool)
}
{( : String : String) -> Bool
return
})
a < b
inclients.sort( a , b
Type Inference
struct Array<String> {
func sort(order: (String, String) -> Bool)
}
{
return
})
a < b
inclients.sort( a, b
Implicit Return
{
return
})
a < b
inclients.sort( a, b
Implicit Return
{ inclients.sort( a, b a < b })
a
Implicit Arguments
{ inclients.sort( a, b < })b
Implicit Arguments
{clients.sort( < })$0 $1
Trailing Closures
clients.sort $1$0{ < })(
Trailing Closures
clients.sort $1$0{ < }
Functional Programming
Functional Programming
println(words)
a
aardvark
aardwolf…
Functional Programming
println(words.filter { $0.hasSuffix("gry") })
Functional Programming
println(words.filter { $0.hasSuffix("gry") })
angry
hungry
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString })
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString })
ANGRY
HUNGRY
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString }
.reduce("HULK") { "($0) ($1)" })
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString }
.reduce("HULK") { "($0) ($1)" })
HULK ANGRY HUNGRY
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString }
.reduce("HULK") { "($0) ($1)" })
HULK ANGRY HUNGRY
Functional Programming
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString }
.reduce("HULK") { "($0) ($1)" })
Functional Programming
println(
GRR!! HULK ANGRY HUNGRY!!!
words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString }
.reduce("HULK") { "($0) ($1)" } )
"GRR!! " +
+ "!!!"
Captures
Captures
func sum(numbers: Int[]) {
var sum = 0
numbers.map {
Captures
func sum(numbers: Int[]) {
var sum = 0
numbers.map {
sum += $0
}
Captures
func sum(numbers: Int[]) {
var sum = 0
numbers.map {
sum += $0
}
Captures
func sum(numbers: Int[]) {
var sum = 0
numbers.map {
sum += $0
}
Captures
func sum(numbers: Int[]) {
var sum = 0
numbers.map {
sum += $0
}
return sum
}
Function Values—Closures
!
!
!
numbers.map {
sum += $0
}
!
!
!
numbers.map
Function Values—Functions
println($0)
{
}
!
!
!
numbers.map (println)
Function Values—Functions
!
!
var indexes = NSMutableIndexSet()
numbers.map
!
Function Values—Methods
indexes.addIndex($0)
{
}
!
!
var indexes = NSMutableIndexSet()
numbers.map
!
(indexes.addIndex)
Function Values—Methods
Closures Are ARC Objects
Closures Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
onTempChange
Closures Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
onTempChange
prev
Closures Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
onTemperatureChange = { next in
println("Changed (next - prev)°F")
prev = next
}
{...}
onTempChange
prev
Closures Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
onTemperatureChange = { next in
println("Changed (next - prev)°F")
prev = next
}
} // scope ends
{...}
onTempChange
prev
Functions Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
func log(next: Int) {
println("Changed (next - prev)°F")
prev = next
}
onTempChange
Functions Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
func log(next: Int) {
println("Changed (next - prev)°F")
prev = next
}
log
onTempChange
prev
Functions Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
func log(next: Int) {
println("Changed (next - prev)°F")
prev = next
}
onTemperatureChange = log
log
onTempChange
prev
Functions Are ARC Objects
var onTemperatureChange: (Int) -> Void = {}
func logTemperatureDifferences(initial: Int) {
var prev = initial
func log(next: Int) {
println("Changed (next - prev)°F")
prev = next
}
onTemperatureChange = log
} // scope ends
log
onTempChange
prev
Ownership of Captures
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
currentTemp = temp
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
{...}
TempNotifier
currentTemp = temp
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
{...}
TempNotifier
currentTemp = tempself.
self
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
{...}
TempNotifier
currentTemp = tempself.
self
onChange
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
{...}
TempNotifier
currentTemp = tempself.
self
onChange
Ownership of Captures
class TemperatureNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
init() {
onChange = { temp in
}
}
}
{...}
TempNotifier
self
onChange
currentTemp = temp
// error: requires explicit 'self'
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
onChange = { temp in
Ownership of Captures
currentTemp = tempself.
}
}
}
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
onChange = { temp in
unowned let uSelf = self
Ownership of Captures
currentTemp = tempself.
}
}
}
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
onChange = { temp in
unowned let uSelf = self
Ownership of Captures
currentTemp = temp
}
}
}
uSelf.
Capture Lists
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
currentTemp = tempself.
}
}
}
onChange = { temp in
Capture Lists
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
currentTemp = tempself.
}
}
}
onChange = {[unowned self] temp in
Capture Lists
class TempNotifier {
var onChange: (Int) -> Void = {}
var currentTemp = 72
!
init() {
currentTemp = tempself.
}
}
}
onChange = {[unowned self] temp in
{...}
TempNotifier
self
onChange
Closures
Closures
Concise, expressive syntax
Closures
Concise, expressive syntax
Simple memory model
Closures
Concise, expressive syntax
Simple memory model
Supports functional programming idioms
Pattern Matching
Joe Groff
Swift Compiler Engineer
func describe(value:
switch value {
case
println("the loneliest number that you'll ever do")
case
println("can be as bad as one")
default:
println("just some number")
}
}
Switch
Int) {
1:
2:
func describe(value:
switch value {
case
println("the loneliest number that you'll ever do")
case
println("can be as bad as one")
default:
println("just some number")
}
}
Switch
"two"
"one"
String) {
:
:
func describe(value:
switch value {
case
println("a few")
case
println("a lot")
default:
println("a ton")
}
}
:
:
String
"two"
"one"
Switch
) {
func describe(value:
switch value {
case
println("a few")
case
println("a lot")
default:
println("a ton")
}
}
:
:5...12
0...4
Int
Switch
) {
enum TrainStatus {
case OnTime
case Delayed
Enumerations
}
enum TrainStatus {
case OnTime
case Delayed
Enumerations
}
(Int)
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
Enumerations
:
")
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
(let minutes)
Enumerations
:
")
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
by (minutes) minutes
(let minutes)
Enumerations
:
")
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
println("let's take (minutes) and come back")
// error: use of unresolved identifier 'minutes'
by (minutes) minutes
(let minutes)
Enumerations
:
")
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
Patterns
:
")
(let minutes)
by (minutes) minutes
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
Patterns
:
")
(let minutes)
by (minutes) minutes
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed
println("delayed
}
Patterns
:
")
(let minutes)
by (minutes) minutes
switch trainStatus {
case .OnTime:
println("on time")
Patterns Compose
switch trainStatus {
case .OnTime:
println("on time")
Patterns Compose
case .Delayed(1):
println("nearly on time")
switch trainStatus {
case .OnTime:
println("on time")
Patterns Compose
case .Delayed(1):
println("nearly on time")
case .Delayed(2...10):
println("almost on time, I swear")
switch trainStatus {
case .OnTime:
println("on time")
Patterns Compose
case .Delayed(1):
println("nearly on time")
case .Delayed(2...10):
println("almost on time, I swear")
case .Delayed(_):
println("it'll get here when it's ready")
enum VacationStatus {
case Traveling(TrainStatus)
case Relaxing(daysLeft: Int)
}
Patterns Compose
Patterns Compose
switch vacationStatus {
Patterns Compose
switch vacationStatus {
case .Traveling(.OnTime):
tweet("Train's on time! Can't wait to get there!")
Patterns Compose
switch vacationStatus {
case .Traveling(.OnTime):
tweet("Train's on time! Can't wait to get there!")
case .Traveling(.Delayed(1...15)):
tweet("Train is delayed.")
Patterns Compose
switch vacationStatus {
case .Traveling(.OnTime):
tweet("Train's on time! Can't wait to get there!")
case .Traveling(.Delayed(1...15)):
tweet("Train is delayed.")
case .Traveling(.Delayed(_)):
tweet("OMG when will this train ride end #railfail")
Patterns Compose
Type Patterns
func tuneUp(car: Car) {
switch car {
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
formulaOne.enterPit()
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
formulaOne.enterPit()
case let raceCar as RaceCar:
if raceCar.hasTurbo { raceCar.tuneTurbo() }
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
formulaOne.enterPit()
case let raceCar as RaceCar:
if raceCar.hasTurbo { raceCar.tuneTurbo() }
fallthrough
Type Patterns
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
formulaOne.enterPit()
case let raceCar as RaceCar:
if raceCar.hasTurbo { raceCar.tuneTurbo() }
fallthrough
default:
car.checkOil()
car.pumpTires()
}
}
Type Patterns
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
Tuple Patterns
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5...1.0, let blue, _):
println("Green and (blue * 100)% blue")
case let (r, g, b, 1.0) where r == g && g == b:
println("Opaque grey (r * 100)%")
Tuple Patterns
Validating a Property List
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
stateFromPlist(["name": "California",
"population": 38_040_000,
"abbr": "CA"])
State(name: California, population: 38040000, abbr: CA)
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
!
stateFromPlist(["name": "California",
"population": "hella peeps",
"abbr": "CA"])
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
!
stateFromPlist(["name": "California",
"population": "hella peeps",
"abbr": "CA"])
nil
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
!
stateFromPlist(["name": "California",
"population": 38_040_000,
"abbr": "Cali"])
Validating a Property List
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State?
!
stateFromPlist(["name": "California",
"population": 38_040_000,
"abbr": "Cali"])
nil
Putting Patterns Together
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case .Some( ):
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case .Some( ):as NSString
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case .Some( ):let listName as NSString
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case
name = listName
.Some( ):let listName as NSString
Putting Patterns Together
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
var name: NSString?
switch list["name"] {
case
name = listName
default:
name = nil
}
.Some( ):let listName as NSString
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
list["name"] {
:
name = listName
default:
name = nil
}
var name: NSString?
.Some( )let listName as NSString
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
:.Some( )let listName as NSString
( ,
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
.Some( )let listName as NSString
( ,
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
where abbr.length == 2:
.Some( )let listName as NSString
( ,
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
where abbr.length == 2:
return State(name: listName, population: pop, abbr: abbr)
.Some( )let listName as NSString
( ,
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
where abbr.length == 2:
return State(name: listName, population: pop, abbr: abbr)
default:
return nil
.Some( )let listName as NSString
( ,
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
func stateFromPlist(list: Dictionary<String, AnyObject>)
-> State? {
!
switch
case
Putting Patterns Together
( , list["population"], list["abbr"])list["name"] {
where abbr.length == 2:
return State(name: listName, population: pop, abbr: abbr)
default:
return nil
}
}
.Some( )let listName as NSString
Pattern Matching
Pattern Matching
Tests the structure of values
Pattern Matching
Tests the structure of values
Improves readability—Patterns are concise and composable
Pattern Matching
Tests the structure of values
Improves readability—Patterns are concise and composable
Improves safety—Variable bindings are tied to the conditions they depend on
Swift
Swift
Optionals
Swift
Optionals
Memory management
Swift
Optionals
Memory management
Initialization
Swift
Optionals
Memory management
Initialization
Closures
Swift
Optionals
Memory management
Initialization
Closures
Pattern matching
More Information
Dave DeLong
App Frameworks and Developer Tools Evangelist
delong@apple.com
!
Documentation
The Swift Programming Language
Using Swift with Cocoa and Objective-C
http://developer.apple.com
!
Apple Developer Forums
http://devforums.apple.com
Related Sessions
• Introduction to Swift Presidio Tuesday 2:00PM
• Advanced Swift Presidio Thusday 11:30AM
• Integrating Swift with Objective-C Presidio Wednesday 9:00AM
• Swift Interoperability in Depth Presidio Wednesday 3:15PM
• Swift Playgrounds Presidio Wednesday 11:30AM
• Introduction to LLDB and the Swift REPL Mission Thursday 10:15AM
• Advanced Swift Debugging in LLDB Mission Friday 9:00AM
Labs
• Swift Tools Lab A Wednesday 2:00PM
• Swift Tools Lab A Thursday 9:00AM
• Swift Tools Lab A Thursday 2:00PM
• Swift Tools Lab A Friday 9:00AM
• Swift Tools Lab A Friday 2:00PM
Intermediate Swift Language by Apple

More Related Content

Similar to Intermediate Swift Language by Apple

NUS iOS Swift Talk
NUS iOS Swift TalkNUS iOS Swift Talk
NUS iOS Swift TalkGabriel Lim
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kirill Rozov
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala AdoptionTomer Gabel
 
My adventure with Elm
My adventure with ElmMy adventure with Elm
My adventure with ElmYan Cui
 
Exploring Koltin on Android
Exploring Koltin on AndroidExploring Koltin on Android
Exploring Koltin on AndroidDeepanshu Madan
 
Perl 6 in Context
Perl 6 in ContextPerl 6 in Context
Perl 6 in Contextlichtkind
 
From android/java to swift (1)
From android/java to swift (1)From android/java to swift (1)
From android/java to swift (1)allanh0526
 
Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Crystal Language
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. ExperienceMike Fogus
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageSmartLogic
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift OverviewKaz Yoshikawa
 
"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, BadooYandex
 
RedDot Ruby Conf 2014 - Dark side of ruby
RedDot Ruby Conf 2014 - Dark side of ruby RedDot Ruby Conf 2014 - Dark side of ruby
RedDot Ruby Conf 2014 - Dark side of ruby Gautam Rege
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swiftPascal Batty
 
Software Dendrology by Brandon Bloom
Software Dendrology by Brandon BloomSoftware Dendrology by Brandon Bloom
Software Dendrology by Brandon BloomHakka Labs
 
Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0Jeremy Gillick
 

Similar to Intermediate Swift Language by Apple (20)

Quick swift tour
Quick swift tourQuick swift tour
Quick swift tour
 
NUS iOS Swift Talk
NUS iOS Swift TalkNUS iOS Swift Talk
NUS iOS Swift Talk
 
Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2Kotlin Basics - Apalon Kotlin Sprint Part 2
Kotlin Basics - Apalon Kotlin Sprint Part 2
 
5 Bullets to Scala Adoption
5 Bullets to Scala Adoption5 Bullets to Scala Adoption
5 Bullets to Scala Adoption
 
My adventure with Elm
My adventure with ElmMy adventure with Elm
My adventure with Elm
 
Exploring Koltin on Android
Exploring Koltin on AndroidExploring Koltin on Android
Exploring Koltin on Android
 
Intro toswift1
Intro toswift1Intro toswift1
Intro toswift1
 
Perl 6 in Context
Perl 6 in ContextPerl 6 in Context
Perl 6 in Context
 
From android/java to swift (1)
From android/java to swift (1)From android/java to swift (1)
From android/java to swift (1)
 
Bulletproofing your foot for Kotlin
Bulletproofing your foot for KotlinBulletproofing your foot for Kotlin
Bulletproofing your foot for Kotlin
 
Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?Por qué Crystal? Why Crystal Language?
Por qué Crystal? Why Crystal Language?
 
Naïveté vs. Experience
Naïveté vs. ExperienceNaïveté vs. Experience
Naïveté vs. Experience
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming Language
 
Programming Language Swift Overview
Programming Language Swift OverviewProgramming Language Swift Overview
Programming Language Swift Overview
 
"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo"Writing Maintainable JavaScript". Jon Bretman, Badoo
"Writing Maintainable JavaScript". Jon Bretman, Badoo
 
RedDot Ruby Conf 2014 - Dark side of ruby
RedDot Ruby Conf 2014 - Dark side of ruby RedDot Ruby Conf 2014 - Dark side of ruby
RedDot Ruby Conf 2014 - Dark side of ruby
 
Think sharp, write swift
Think sharp, write swiftThink sharp, write swift
Think sharp, write swift
 
Software Dendrology by Brandon Bloom
Software Dendrology by Brandon BloomSoftware Dendrology by Brandon Bloom
Software Dendrology by Brandon Bloom
 
Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0
 

Recently uploaded

A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyAnusha Are
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024Mind IT Systems
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxalwaysnagaraju26
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...Nitya salvi
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456KiaraTiradoMicha
 

Recently uploaded (20)

A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...Chinsurah Escorts ☎️8617697112  Starting From 5K to 15K High Profile Escorts ...
Chinsurah Escorts ☎️8617697112 Starting From 5K to 15K High Profile Escorts ...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 

Intermediate Swift Language by Apple