Intermediate Swift - Session 403
Options
String to Integer
Optional Type
var optionalNumber:Int?
// default initialized to nil
optionalNumber = 6
Non-Optional Types can't be nil
var myString:String = nil
// error
Optional Return Types
func findIndexOfString(string:String, array:String[]) -> Int? {
for (index, value) in enumerate(array) {
if value == string {
return index
}
}
return nil
}
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, not nil?, indexValue is of type Int
if let indexValue = findIndexOfString("Anna", neighbors) { // index is of type Int, not nil?, indexValue is of type Int
println("Hello, \(neighbors[indexValue])")
}
else {
println("Must've moved away")
}
Optional Chaining
if let addressNumber = paul.residence?.address?.buildingNumber?.toInt() {
addToDatabase("Paul", addressNumber)
}
- Use
if let
optional binding to test and unwrap at the same time - Option chaining (?) is a concise way to work with chained optionals
Memory Management
Automatic Reference Counting
Weak References are optional values
Binding the optional produces a strong reference
if let tenant = apt.tenant {
tenant.buzzIn()
}
apt.tenant?.buzzIn()
Unowned References
Strong, Weak, and Unowned References
strong references are default
Initialization
Every value must
be initialized before it is used.
class RaceCar:Car {
var hasTurbo:Bool
init(color:Color, turbo:Bool) {
hasTurbo = turbo
super.init(color:color)
}
// 多個 initializers
convenience init(color:Color) {
self.init(color:color, turbo:true)
}
convenience init() {
self.init(color:Color(gray:0.4))
}
}
class FormulaOne:RaceCar {
let minimumWeight = 642
init(Color:Color) {
self.init(color:color, turbo:false)
}
}
Lazy Properties
@lazy var multiplayerManager = MultiplayerManager()
Deinitialization
class FileHandle {
let fileDescriptor:FileDescriptor
init(path:String) {
fileDescriptior = openFile(path)
}
deinit {
closeFile(fileDescriptor)
}
}
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 youe need them
Closures
var clients = ["Pestov", "Buenaventura", "Sreeram", "Babbage"]
clients.sort({(a:String, b:String) -> Bool in
return a < b
})
println(clients)
用 Type Inference
簡化成
struct Array<String> {
func sort(order:(String, String) -> Bool)
}
clients.sort({a, b in a < b})
Implicit Arguments
clients.sort({ $0 < $1 })
Trailing Closures
client.sort { $0 < $1 }
Functional Programming
println(words.filter { $0.hasSuffix("gry") })
// angry
// hungry
println(words.filter { $0.hasSuffix("gry") }
.map { $0.uppercaseString })
// ANGRY
// HUNGRY
Function Values - Closures
numbers.map {
// sum += $0
println($0)
}
// 可以簡化成
numbers.map(println)
var indexes = NSMutableIndexSet()
numbers.map {
indexes.addIndex($0)
}
// 可以簡化成
numbers.map(indexes.addIndex)
Capture Lists
class TempNotifier {
var onChange:(Int) -> Void = {}
var currentTemp = 72
init() {
onChange = {[unowned self] temp in
self.currentTemp = temp
}
}
}
Pattern Matching
Validating a Property List
func stateFromPlist(list:Dictionary<String, AnyObject>) -> State?
// 正常狀況
stateFromPlist("name": "California"
"population", 38_040_000,
"abbr": "CA")
// 當傳入錯誤的型別
// ie: population 應該要傳入數字,卻傳入字串,需要回傳 nil
stateFromPlist("name": "California"
"population", "hella peeps",
"abbr": "CA")
可以用這樣的方式檢查
func stateFromPlist(list:Dictionary<String, AnyObject>) -> State? {
var name:NSString?
switch list["name"] {
case .Some(let listName as NSString):
name = listName
// ...
default:
name = nil
}
return name
}
有更好的方法
func stateFromPlist(list:Dictionary<String, AnyObject>) -> State? {
switch (list["name"], list["population"], list["abbr"]) {
case (.Some(let listName as NSString),
.Some(let pop as NSNumber),
.Some(let abbr as NSString))
where abbr.length ==2:
// 用 where 檢查 abbr 長度是否為2
return State(name:listName, population:pop, abbr:abbr)
default:
return nil
}
}
總結
- Optionals
- Memory management
- Initialization
- Closures
- Pattern matching