WWDC 2014 Brain Lanier
- Cleaner alternative to using sentinels (
NULL
,NSNotFound
, etc.) to represent invalid values - optionals are initialized to nil by default
var optionalNumber: Int?
nil
is a sentinel value that works with any type- value is wrapped in optional by setter
optionalNumber = 6
- Non-optional types can't be nil
var myString: String = nil
enumerate
returns(index, value)
for each element in an array
let index: Int? = findIndexOfString("Madison", neighbors)
// if index is not nil, its value will be assigned to indexValue
if let value = funcReturningOptional("foo") {
// do something
}
addressNumber = paul.residence?.address?.buildingNumber?.toInt()
- c.f. passing messages to
nil
in obj-c
if let value = paul.residence?.address?.toInt() {
}
enun Optional<T> {
case None
case Some(T)
}
- Swift uses ARC
- Reference cycles
- use weak references
weak var Person
- Weak references are optionals
- Binding a weak reference with
let
produces a strong reference - Testing a weak reference doesn't produce a strong reference
- Chaining doesn't preserve a strong reference between method invocations
- Binding a weak reference with
- Unowned refs can be used just like strong refs
- Use strong references from owners to the objects they own
- Use weak refs among objects with independent lifetimes
- Use unowned references from owned objects with the same lifetime
- great for back references from dependent objects back up to their owners
- Every value must be initialized before it is used
- Swift doesn't default initialize variables, constants, or properties
- optionals are the one exception
- use of an uninitialized variable is a compiler error
- handle responsibility of fully initializing an instance
struct Color {
let red = 1.0, green = 1.0, blue = 1.0
init(grayScale: Double) {
red = grayScale
green = grayScale
blue = grayScale
}
}
- member-wise initializer, default initializer
- call superclass's initializer after setting own properties
- ensures memory safety
- superclass may modify properties at the end of its initializer
- subclass must set its own properties before letting the superclass
- Designated initializers only delegate up
- Convenience initializers only delegate across
convenience init() {
self.init(color: Color(gray: 0.4))
}
- not inherited by default
- if all properties are given default values and there's no initializer, all superclass initializers are inherited
@lazy var multiplayerManager = MultiplayerManager()
- Only initialized once when first accessed
deinit {
closeFile(fileDescriptor)
}
clients.sort){(a: String, b: String) -> Bool in
return a < b
}
sort
knows that it takes two strings and returns a bool
clients.sort {a, b in
return a < b
}
- single expression closure implicitly returns
clients.sort({a, b in a < b})
clients.sort({$1 < $2})
words.filter {$0.hasSuffix("gry")} .map {$0.uppercaseString }
- functions can be used wherever closures are used
- storing a closure property that references self creates a reference cycle. Use
unowned
unowned let uSelf = self
onChange = { temp in
uSelf.currentTemp = temp
}
- Even better: Specify how closure should capture its local state
onChange = { [unowned self] temp in
self.currentTemp = temp
}
enum Status {
case OnTime
case Delayed(Int)
}
switch trainStatus {
case .OnTime:
println("on time")
case .Delayed(let minutes)
case .Delayed(2)
case .Delayed(2..10):
case .Delayed(_)
}
switch vacationStatus {
case .Traveling(.OnTime):
case .Traveling(.Delayed(1..15)):
}
func tuneUp(car: Car) {
switch car {
case let formulaOne as FormulaOne:
formulaOne.enterPit()
//...
}
let color = (1.0, 1.0, 1.0, 1.0)
switch color {
case (0.0, 0.5..1.0, let blue, _):
//
case let (r, g, b, 1.0) where r == g && g == b:
//
}
func stateFromPlist(list: Dictionary<String, AnyObject>) -> State? {
switch (list["name"], list["population], list["abbr"]) {
case (.Some(let name as String),
.Some(let pop as Int),
.Some(let abbr as String))
where abbr. length == 2:
return State(name: name, population: pop, abbr: abbr)
default:
return nil
}
}