Swift 2.0
変更点(だいたい)まとめ
Error Handling
Representing and Throwing Errors
// Errorを定義する
enum VendingMachineError: ErrorType {
case InvalidSelection
case InsufficientFunds(coinsNeeded: Int)
case OutOfStock
}
// Errorをthrowする
throw VendingMachineError.InsufficientFunds(coinsNeeded: 5)
Handling Errors
class VendingMachine {
// Errorをthrowするfunctionにはthrowsつける
func vend(name: String, coins: Int) throws -> Int {
guard let item = inventory[name] else {
throw VendingMachineError.InvalidSelection
}
return coins - item.price
}
}
Handling Errors
// Errorを処理しないので、throwsをつけて呼び出し元に任せる
func buyFavoriteSnack(person: String, coins: Int) throws -> Int {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
// Errorをthrowするfunctionの呼び出し元は、tryしないとビルドエラー
return try vendingMachine.vend(snackName, coins: coins)
}
Handling Errors
// Errorをdo – catchで処理する
func buyFavoriteSnack(person: String, coins: Int) -> Int {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
do {
return try vendingMachine.vend(snackName, coins: coins)
} catch VendingMachineError.InvalidSelection {
print("Invalid selection.")
} catch VendingMachineError.InsufficientFunds(let coinsNeeded) {
print("Please insert an additional (coinsNeeded) coins.")
} catch {
print("Unknown Error.")
}
}
Handling Errors
func buyFavoriteSnack(person: String, coins: Int) -> Int {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
// try?にすると、returnがOptionalになる
// Errorのときは、ランタイムエラーにならず、returnがnilになる
return try? vendingMachine.vend(snackName, coins: coins) ?? coins
}
Handling Errors
func buyFavoriteSnack(person: String, coins: Int) -> Int {
let snackName = favoriteSnacks[person] ?? "Candy Bar"
// try!にすると、ビルドエラーは無くなるけど、
// Error発生時にはランタイムエラーになるので危険
return try! vendingMachine.vend(snackName, coins: coins)
}
Specifying Cleanup Actions
func processFile(filename: String) throws {
if exists(filename) {
let file = open(filename)
defer { // 開いたリソースの閉じる処理を近くに書いとく
close(file)
}
while let line = try file.readline() {
// TODO
}
// scope終了時にdeferの中が呼ばれて、リソースが閉じられる
// 同じscopeに複数のdeferを書いたときは、逆順に呼ばれる
}
}
Control Flow
Repeat-While
// do – whileと同じ
// 一回実行してから繰り返し条件を判断する
var num: Int
repeat {
num = random()
} while num < 100
Guard
func vend(name: String, coins: Int) throws -> Int {
// 前提条件検証に特化した条件分岐
// elseまでセットなので、正しい方の条件を書く
// let / varで宣言した変数はguardの外のscopeになる
// elseはreturn, break, continue, throwで抜けないとコンパイルエラー
guard let item = inventory[name] else {
throw VendingMachineError.InvalidSelection
}
return coins - item.price
}
If Case(Pattern Match)
enum Gender {
case Male, Female
}
let person: (String, Int, Gender) = ("Ken", 33, .Male)
// ifとguardでもcaseが使える
if case (_, 20..<65, _) = person {
print("Worker!")
}
if case (let name, _, .Male) = person {
print(name)
}
Optional Pattern
let nums: [Int?] = [nil, 2, 3, nil, 5]
for case let num? in nums { // nilを除いたループ。numはInt?じゃなくてInt
print(num) // 2, 3, 5
}
for case let num? in nums where num % 2 == 1 {
print(num) // 3, 5
}
Checking API Availability
// ランタイムのプラットホームとバージョン(以上)を判定できる
// ifとguardの条件でのみ使える
// プラットホームは、「iOS」「OSX」「watchOS」が使える
// バージョンは、メジャーだけからサブマイナーまで書ける
// 最後の要素は、絶対「*」になる
if #available(iOS 9, OSX 10.10, *) {
// Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X
} else {
// Fall back to earlier iOS and OS X APIs
}
Protocol Extensions
Protocol Extensions
protocol MyProtocol {
func abstractFunc()
func defaultFunc()
}
extension MyProtocol {
// functionのデフォルト実装を書ける
func defaultFunc() { … }
// protocolにないfunctionも書ける(privateもOK)
func newFunc() { … }
}
Protocol Extensions
// extensionで実装したメソッドは実装しなくてもOK
class MyClass: MyProtocol {
func abstractFunc() { … }
}
MyClass().abstractFunc()
MyClass().defaultFunc()
MyClass().newFunc()
class MyClass2: MyProtocol {
func abstractFunc() { … }
func defaultFunc() { … } // extensionのデフォルト実装は上書きできる
func newFunc() { … } // extensionだけに書いたメソッドも上書きできる
}
その他
Enumerations
Implicitly Assigned Raw Values
// 最初の要素を明示しない場合は0になる
// 以降の要素を明示しない場合、直前の要素をインクリメントした値になる
enum Planet: Int {
// 0, 1, 5, 6, 7, 10, 11, 12
case Mercury, Venus, Earth = 5, Mars, Jupiter, Saturn = 10, Uranus, Neptune
}
// 明示しない場合は、名前と同じになる
enum CompassPoint: String {
// "North", "南", "East", "West"
case North, South = "南", East, West
}
Enumerations
Recursive Enumerations
// 自身をネストしたenumが作れる
// ネストするものにindirectをつける
enum ArithmeticExpression {
case Number(Int)
indirect case Addition(ArithmeticExpression, ArithmeticExpression)
indirect case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
// enum自体につけることもできる
indirect enum ArithmeticExpression {
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
case Multiplication(ArithmeticExpression, ArithmeticExpression)
}
Expressions
Initializer Expression
class MyClass {
init(i: Int) { … }
init(s: String) { … }
init(i: Int, s: String) { … }
}
// Initializerを取れるようになった
let init1: Int -> MyClass = MyClass.init
let init2: String -> MyClass = MyClass.init
let init3: (Int, String) -> MyClass = MyClass.init
let initializer: Int -> String = String.init
let s: String = [1, 2, 3].map(initializer).reduce("", combine: +) // "123"
Functions
Variadic Parameters
// 可変長引数を末尾以外にも書ける(ただし1つまで)
func print(items: Any..., separator: String = default, terminator: String = default)
print(1, 2, 3, separator: ", ", terminator: ".") // "1, 2, 3."
String Literals
// 文字列リテラルの+演算子での結合は、
// 実行時ではなく、コンパイル時に処理される
// textAとtextBは実行時には同じ
let textA = "Hello " + "world"
let textB = "Hello world"
• Functionのラベルのつけ方が変更になってる
– 第一引数に#つけられなくなった。けど、自由にラ
ベルをつけられる
– 第一引数以外に#をつけると、呼ぶ時にラベル不
要
• Label付きのbreakで、ifとswitchもbreakできる
ようになった

Swift 2.0 変更点(だいたい)まとめ

  • 1.
  • 2.
  • 3.
    Representing and ThrowingErrors // Errorを定義する enum VendingMachineError: ErrorType { case InvalidSelection case InsufficientFunds(coinsNeeded: Int) case OutOfStock } // Errorをthrowする throw VendingMachineError.InsufficientFunds(coinsNeeded: 5)
  • 4.
    Handling Errors class VendingMachine{ // Errorをthrowするfunctionにはthrowsつける func vend(name: String, coins: Int) throws -> Int { guard let item = inventory[name] else { throw VendingMachineError.InvalidSelection } return coins - item.price } }
  • 5.
    Handling Errors // Errorを処理しないので、throwsをつけて呼び出し元に任せる funcbuyFavoriteSnack(person: String, coins: Int) throws -> Int { let snackName = favoriteSnacks[person] ?? "Candy Bar" // Errorをthrowするfunctionの呼び出し元は、tryしないとビルドエラー return try vendingMachine.vend(snackName, coins: coins) }
  • 6.
    Handling Errors // Errorをdo– catchで処理する func buyFavoriteSnack(person: String, coins: Int) -> Int { let snackName = favoriteSnacks[person] ?? "Candy Bar" do { return try vendingMachine.vend(snackName, coins: coins) } catch VendingMachineError.InvalidSelection { print("Invalid selection.") } catch VendingMachineError.InsufficientFunds(let coinsNeeded) { print("Please insert an additional (coinsNeeded) coins.") } catch { print("Unknown Error.") } }
  • 7.
    Handling Errors func buyFavoriteSnack(person:String, coins: Int) -> Int { let snackName = favoriteSnacks[person] ?? "Candy Bar" // try?にすると、returnがOptionalになる // Errorのときは、ランタイムエラーにならず、returnがnilになる return try? vendingMachine.vend(snackName, coins: coins) ?? coins }
  • 8.
    Handling Errors func buyFavoriteSnack(person:String, coins: Int) -> Int { let snackName = favoriteSnacks[person] ?? "Candy Bar" // try!にすると、ビルドエラーは無くなるけど、 // Error発生時にはランタイムエラーになるので危険 return try! vendingMachine.vend(snackName, coins: coins) }
  • 9.
    Specifying Cleanup Actions funcprocessFile(filename: String) throws { if exists(filename) { let file = open(filename) defer { // 開いたリソースの閉じる処理を近くに書いとく close(file) } while let line = try file.readline() { // TODO } // scope終了時にdeferの中が呼ばれて、リソースが閉じられる // 同じscopeに複数のdeferを書いたときは、逆順に呼ばれる } }
  • 10.
  • 11.
    Repeat-While // do –whileと同じ // 一回実行してから繰り返し条件を判断する var num: Int repeat { num = random() } while num < 100
  • 12.
    Guard func vend(name: String,coins: Int) throws -> Int { // 前提条件検証に特化した条件分岐 // elseまでセットなので、正しい方の条件を書く // let / varで宣言した変数はguardの外のscopeになる // elseはreturn, break, continue, throwで抜けないとコンパイルエラー guard let item = inventory[name] else { throw VendingMachineError.InvalidSelection } return coins - item.price }
  • 13.
    If Case(Pattern Match) enumGender { case Male, Female } let person: (String, Int, Gender) = ("Ken", 33, .Male) // ifとguardでもcaseが使える if case (_, 20..<65, _) = person { print("Worker!") } if case (let name, _, .Male) = person { print(name) }
  • 14.
    Optional Pattern let nums:[Int?] = [nil, 2, 3, nil, 5] for case let num? in nums { // nilを除いたループ。numはInt?じゃなくてInt print(num) // 2, 3, 5 } for case let num? in nums where num % 2 == 1 { print(num) // 3, 5 }
  • 15.
    Checking API Availability //ランタイムのプラットホームとバージョン(以上)を判定できる // ifとguardの条件でのみ使える // プラットホームは、「iOS」「OSX」「watchOS」が使える // バージョンは、メジャーだけからサブマイナーまで書ける // 最後の要素は、絶対「*」になる if #available(iOS 9, OSX 10.10, *) { // Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X } else { // Fall back to earlier iOS and OS X APIs }
  • 16.
  • 17.
    Protocol Extensions protocol MyProtocol{ func abstractFunc() func defaultFunc() } extension MyProtocol { // functionのデフォルト実装を書ける func defaultFunc() { … } // protocolにないfunctionも書ける(privateもOK) func newFunc() { … } }
  • 18.
    Protocol Extensions // extensionで実装したメソッドは実装しなくてもOK classMyClass: MyProtocol { func abstractFunc() { … } } MyClass().abstractFunc() MyClass().defaultFunc() MyClass().newFunc() class MyClass2: MyProtocol { func abstractFunc() { … } func defaultFunc() { … } // extensionのデフォルト実装は上書きできる func newFunc() { … } // extensionだけに書いたメソッドも上書きできる }
  • 19.
  • 20.
    Enumerations Implicitly Assigned RawValues // 最初の要素を明示しない場合は0になる // 以降の要素を明示しない場合、直前の要素をインクリメントした値になる enum Planet: Int { // 0, 1, 5, 6, 7, 10, 11, 12 case Mercury, Venus, Earth = 5, Mars, Jupiter, Saturn = 10, Uranus, Neptune } // 明示しない場合は、名前と同じになる enum CompassPoint: String { // "North", "南", "East", "West" case North, South = "南", East, West }
  • 21.
    Enumerations Recursive Enumerations // 自身をネストしたenumが作れる //ネストするものにindirectをつける enum ArithmeticExpression { case Number(Int) indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) } // enum自体につけることもできる indirect enum ArithmeticExpression { case Number(Int) case Addition(ArithmeticExpression, ArithmeticExpression) case Multiplication(ArithmeticExpression, ArithmeticExpression) }
  • 22.
    Expressions Initializer Expression class MyClass{ init(i: Int) { … } init(s: String) { … } init(i: Int, s: String) { … } } // Initializerを取れるようになった let init1: Int -> MyClass = MyClass.init let init2: String -> MyClass = MyClass.init let init3: (Int, String) -> MyClass = MyClass.init let initializer: Int -> String = String.init let s: String = [1, 2, 3].map(initializer).reduce("", combine: +) // "123"
  • 23.
    Functions Variadic Parameters // 可変長引数を末尾以外にも書ける(ただし1つまで) funcprint(items: Any..., separator: String = default, terminator: String = default) print(1, 2, 3, separator: ", ", terminator: ".") // "1, 2, 3."
  • 24.
    String Literals // 文字列リテラルの+演算子での結合は、 //実行時ではなく、コンパイル時に処理される // textAとtextBは実行時には同じ let textA = "Hello " + "world" let textB = "Hello world"
  • 25.
    • Functionのラベルのつけ方が変更になってる – 第一引数に#つけられなくなった。けど、自由にラ ベルをつけられる –第一引数以外に#をつけると、呼ぶ時にラベル不 要 • Label付きのbreakで、ifとswitchもbreakできる ようになった