---
title: Swift 2.0 で変わったところ「前編」 #cswift
tags:  #カジュアルswift勉強会 #swift  
author: [熊谷友宏](https://convert.docswell.com/user/es_kumagai)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/LE1KNKN4JG.jpg?width=480
description: 2015.07.25 に開催した『カジュアル Swift 勉強会』で、Swift 2.0 での変更点をざっくりと紹介してみました。気づいた全部を紹介するつもりでいたんですけど、思いのほか量が多くてひとまずは「前編」という形で、とりわけ目立つ変更点を取り上げてみます。  ※ Docswell での公開に移行する直前の Slideshare での閲覧数は 28,765 でした。
published: July 26, 15
canonical: https://convert.docswell.com/s/es_kumagai/ZXEW93-cswiftswift2-150725222618-lva1-app6891
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/LE1KNKN4JG.jpg)

Swift  カジュアルプログラミング
Swift  2.0  で変わったところ
（前編）
2015.07.25  
@  カジュアル  Swift  勉強会  #1
EZ-‐‑‒NET  熊⾕谷友宏  
http://ez-‐‑‒net.jp/


# Page. 2

![Page Image](https://bcdn.docswell.com/page/GEWD4D4ZJ2.jpg)

熊谷友宏
EZ-NET http://ez-net.jp/
@es̲kumagai
̶ 勉強会開催 ̶
#yidev 横浜 iPhone 開発者勉強会
カジュアル Swift 勉強会 @ 青葉台
Xcode 5 徹底解説
MOSA
IP Phone
音でダイヤル
いつもの電卓
with 割勘ウォッチ
音で再配達ゴッド


# Page. 3

![Page Image](https://bcdn.docswell.com/page/47ZG2G2LE3.jpg)

新言語 Swift 登場
2014.06.02 @ WWDC 2014
Swift 2.0 登場
2015.06.08 @ WWDC 2015


# Page. 4

![Page Image](https://bcdn.docswell.com/page/YJ6YVYVM7V.jpg)

大幅な仕様変更
？


# Page. 5

![Page Image](https://bcdn.docswell.com/page/GJ5GDGDQJ4.jpg)

そこで


# Page. 6

![Page Image](https://bcdn.docswell.com/page/LE3RMRMZ75.jpg)

Swift 2.0 で変わったところを
ざっくり紹介してみる


# Page. 7

![Page Image](https://bcdn.docswell.com/page/8EDY6Y64EG.jpg)

1/4
制御構文


# Page. 8

![Page Image](https://bcdn.docswell.com/page/V7P6Y6YVJ8.jpg)

guard


# Page. 9

![Page Image](https://bcdn.docswell.com/page/2JV3G3GREQ.jpg)

guard《予防線》
▶ 以降、条件式を満たすことを保証
▶ 満たさなければスコープの終了を保証
▶ 早期 Exit
guard expression else {
// 条件を満たさない場合は
// ここでスコープを抜ける実装を書く
}
// これ以降は条件を満たしていることを保証


# Page. 10

![Page Image](https://bcdn.docswell.com/page/5EG383867L.jpg)

guard
早期 Exit を保証
guard value != 0 else {
// ここでスコープを抜けるコードを書かないとエラー
}
&#039;guard&#039; body may not fall through, consider
using &#039;return&#039; or &#039;break&#039; to exit the scope
▶ return
▶ break
▶ continue
▶ fatalError


# Page. 11

![Page Image](https://bcdn.docswell.com/page/4JQ595927P.jpg)

guard
変数が 0 以外であることを保証
guard value2 != 0 else {
// 0 の場合は結果を 0 とみなす
}
return 0
// これ以降は 0 ではないこと前提で記載できる
return value1 / value2


# Page. 12

![Page Image](https://bcdn.docswell.com/page/K749X9XPE1.jpg)

guard
変数が nil でないことを保証
guard let value = optional else {
// nil の場合は結果を .Unknown とする
}
return .Unknown
// これ以降は value を使ってコーディングできる
let data = calculate(value)


# Page. 13

![Page Image](https://bcdn.docswell.com/page/LJ1KNKNX7G.jpg)

guard
複雑な条件を指定して保証
guard let path = getPath()
where path.hasPrefix(&quot;/Volumes&quot;) else {
}
fatalError()
// 変数 path が &quot;/Volumes&quot; で始まることを保証


# Page. 14

![Page Image](https://bcdn.docswell.com/page/GJWD4D4K72.jpg)

defer


# Page. 15

![Page Image](https://bcdn.docswell.com/page/4EZG2G2NJ3.jpg)

defer《繰り延べ》
▶ スコープを抜ける直前に実行する
▶ defer の内部で
直前までに宣言された変数が使える
defer {
// スコープを抜ける寸前に実行したい処理を記載
}


# Page. 16

![Page Image](https://bcdn.docswell.com/page/Y76YVYV9EV.jpg)

defer
スコープを抜ける直前に実行
var handle:Handle = File.open(path)
// 最後に必ずリソースを閉じる
defer {
}
handle.close()
// スコープを抜けない限りはリソースを使える
string.writeTo(&amp;handle)


# Page. 17

![Page Image](https://bcdn.docswell.com/page/G75GDGDD74.jpg)

defer
複数の defer を実行
defer {
}
print(1)
defer {
}
print(2)
▶ 最後にスタック順に実行
2→1


# Page. 18

![Page Image](https://bcdn.docswell.com/page/9J2Y8DMMJR.jpg)

defer
入れ子にして defer を実行
defer {
defer {
}
}
print(1)
print(2)
▶ defer を抜ける直前で実行
2→1


# Page. 19

![Page Image](https://bcdn.docswell.com/page/DEYG62XPEM.jpg)

defer
複数呼び出しと入れ子の複合
defer {
defer {
}
}
print(1)
print(2)
defer {
}
print(3)
▶ ルールどおりの順序
3→2→1


# Page. 20

![Page Image](https://bcdn.docswell.com/page/VJNGZ81M78.jpg)

repeat-while


# Page. 21

![Page Image](https://bcdn.docswell.com/page/YE9WZK5WE3.jpg)

repeat-while《繰り返し》
▶ ブロックを実行し、最後に条件判定
▶ 従前の do-while 構文
▶ 条件式は repeat ブロックの外の扱い
repeat {
// 処理を書く
// この処理を実行後に条件判定
} while expression


# Page. 22

![Page Image](https://bcdn.docswell.com/page/GE8N1RYR7D.jpg)

repeat-while
実行後に条件判定
var count = 100
repeat {
// 先にブロックを実行
--count
} while count &gt; 0 // ブロックを抜けて条件判定


# Page. 23

![Page Image](https://bcdn.docswell.com/page/LELPQK427R.jpg)

repeat-while
スコープ内の変数は使えない
let value = 100
repeat {
// while 条件式はスコープの外
let condition = array.contains(value)
} while condition // repeat 内の変数は使えない
Use of unresolved identiﬁer &#039;condition&#039;


# Page. 24

![Page Image](https://bcdn.docswell.com/page/4JM412K97W.jpg)

上⼿手な
repeat-while の
使いどころが想像できない


# Page. 25

![Page Image](https://bcdn.docswell.com/page/PJRWLMX979.jpg)

do-catch


# Page. 26

![Page Image](https://bcdn.docswell.com/page/PEXPWV637X.jpg)

do-catch《エラーハンドリング》
▶ エラーハンドリング専用構文
▶ 投げられた ErrorType を捕捉
▶ ErrorType は列挙型または NSError
do {
// エラーが発生する可能性のあるコードを記載
} catch {
// ここでエラー処理を行う
}


# Page. 27

![Page Image](https://bcdn.docswell.com/page/3EKDVQ1NJD.jpg)

do-catch
エラーの発生と捕捉
do {
// エラーが発生するポイントで try を明記
var handle = try File.open(path)
// エラーがなければスコープ内の処理を続行
} catch {
// エラー発生時のみ実行
// ErrorType 型の error 変数を参照可能
}
print(error)


# Page. 28

![Page Image](https://bcdn.docswell.com/page/L73RMPQZJ5.jpg)

2/4
Error Handling


# Page. 29

![Page Image](https://bcdn.docswell.com/page/87DY6L947G.jpg)

Error Handling


# Page. 30

![Page Image](https://bcdn.docswell.com/page/VJP6Y2ZVE8.jpg)

Error Handling
エラーの定義方法
// 列挙型でエラーを定義
enum FileOperationError : ErrorType {
}
case FailedToOpen
case NotPermitted(String)
▶ 列挙型を ErrorType に準拠
▶ 列挙型がエラードメイン
▶ 列挙子で関連するエラーを定義する


# Page. 31

![Page Image](https://bcdn.docswell.com/page/2EV3GDWR7Q.jpg)

Error Handling
エラーの送出方法
// 列挙子を指定してエラー送信
throw FileOperationError.FailedToOpen
// NSError でエラーを送信
throw NSError(domain:
NSInvalidArgumentException,
code: 0, userInfo: nil)


# Page. 32

![Page Image](https://bcdn.docswell.com/page/57G38YD6JL.jpg)

Error Handling
エラーを詳しく捕捉
do {
var handle = try File.open(path)
} catch FileOperationError.FailedToOpen {
// エラーの種類を明記して捕捉
} catch {
// すべてのエラーの捕捉も必須
}


# Page. 33

![Page Image](https://bcdn.docswell.com/page/4EQ59M12JP.jpg)

Error Handling
値付きのエラーを捕捉
do {
var handle = try File.open(path)
} catch FileOperationError
.NotPermitted(let reason) {
// 列挙子に添えられた値を取り出して使える
} catch {
// すべてのエラーの捕捉も必須
}


# Page. 34

![Page Image](https://bcdn.docswell.com/page/KJ49XVRP71.jpg)

Error Handling
エラーを大雑把に捕捉（詳細を変数で捕捉）
do {
var handle = try File.open(path)
} catch let error as FileOperationError {
// 列挙型全体で捕捉
} catch {
// すべてのエラーの捕捉も必須
}


# Page. 35

![Page Image](https://bcdn.docswell.com/page/LE1KN3QXJG.jpg)

Error Handling
エラーを大雑把に捕捉（詳細を破棄）
do {
var handle = try File.open(path)
} catch is FileOperationError {
// 列挙型全体で捕捉
} catch {
// すべてのエラーの捕捉も必須
}


# Page. 36

![Page Image](https://bcdn.docswell.com/page/GEWD4PMKJ2.jpg)

Error Handling
スコープ内で投げたエラーも捕捉可能
do {
// スコープ内で明示的に投げたエラーも捕捉可能
throw FileOperationError.FailedToOpen
} catch FileOperationError.FailedToOpen {
// エラー処理が実行される
}


# Page. 37

![Page Image](https://bcdn.docswell.com/page/47ZG2KQNE3.jpg)

NSError Handing


# Page. 38

![Page Image](https://bcdn.docswell.com/page/YJ6YVQ697V.jpg)

NSError Handling
ErrorType は NSError にキャスト可能
let error
= FileOperationError.FailedToOpen as NSError
▶ Error Domain は列挙型名
▶ Error Code は 0
▶ Description は
“The operation couldnʼt be completed. (…)”


# Page. 39

![Page Image](https://bcdn.docswell.com/page/GJ5GDR6DJ4.jpg)

NSError Handling
捕捉時に NSError に変換可能
do {
var handle = try File.open(path)
} catch let error as NSError {
// NSError と一緒に扱える
}
print(error.localizedDescription)


# Page. 40

![Page Image](https://bcdn.docswell.com/page/9E2Y8DNMER.jpg)

エラーの扱い


# Page. 41

![Page Image](https://bcdn.docswell.com/page/D7YG62PP7M.jpg)

エラーの扱い
エラーが起こり得ないなら
do {
var handle = try! File.open(path)
} catch {
}
▶ エラーが起こり得ないなら try!
▶ do-catch が不要
▶ もしエラーが発生すると強制終了


# Page. 42

![Page Image](https://bcdn.docswell.com/page/VENGZ85MJ8.jpg)

エラーの扱い
呼び出し元にエラー処理を委ねる
// 引数リストの次に throws を記載
func execute() throws -&gt; String {
// 捕捉しないエラーを呼び出し元へ throw する
var handle = try File.open(path)
}


# Page. 43

![Page Image](https://bcdn.docswell.com/page/Y79WZKYW73.jpg)

エラーの扱い
エラーの一部を呼び出し元に委ねる
func execute() throws -&gt; String {
// エラーの一部を捕捉する
do {
var handle = try File.open(path)
}
catch FileOperationError.NotPermitted {
}
// 捕捉しなかったエラーは呼び出し元に委ねる
}


# Page. 44

![Page Image](https://bcdn.docswell.com/page/G78N1R6RJD.jpg)

エラーの扱い
引数でエラーを発生するかを決める
// エラーが起こり得る関数を引数にとり
// 関数リストの後に rethrows を明記
func execute(f:() throws -&gt; Void) rethrows
-&gt; String {
try f()
// 受け取った関数以外でエラーは発生できない
}


# Page. 45

![Page Image](https://bcdn.docswell.com/page/L7LPQK92JR.jpg)

エラーの扱い
引数でエラーを発生するかを決める
// エラーが起こり得る関数を引数にとり
// 関数リストの後に rethrows を明記
func execute(f:() throws -&gt; Void) rethrows
-&gt; String {
try f()
// 受け取った関数以外でエラーは発生できない
}
throw FileOperationError.FailedToOpen
&#039;rethrows&#039; function may only throw by
calling a parameter function


# Page. 46

![Page Image](https://bcdn.docswell.com/page/4EM412Z9JW.jpg)

エラーの扱い
引数でエラーが発生するかが決まる
// エラーが発生するかもしれない関数を渡せる
// その場合は try が必要になる
try execute { () throws -&gt; Void in
}
// エラーが発生しない関数も渡せる
// その場合は try が不要（エラーが起こり得ない）
execute { () -&gt; Void in
}
rethrows 指定の関数に限り好きな方を渡せる


# Page. 47

![Page Image](https://bcdn.docswell.com/page/PERWLM69J9.jpg)

3/4
詳細な条件指定


# Page. 48

![Page Image](https://bcdn.docswell.com/page/P7XPWVM3JX.jpg)

Pattern Matching


# Page. 49

![Page Image](https://bcdn.docswell.com/page/37KDVQGNED.jpg)

Pattern Matching
列挙子を扱う（前提）
// このような場面を想定したとき
enum Platform {
}
case IOS(Double)
case OSX(Double)
let platform = Platform.OSX(10.11)


# Page. 50

![Page Image](https://bcdn.docswell.com/page/LJ3RMPNZE5.jpg)

Pattern Matching
if 文で列挙子を判定
// 列挙子から直接、添えた値を抽出可能
if case .OSX = platform {
}


# Page. 51

![Page Image](https://bcdn.docswell.com/page/8JDY6LW4JG.jpg)

Pattern Matching
列挙子に添えた値を抽出
// 列挙子から直接、添えた値を抽出可能
if case let .OSX(version) = platform {
print(version)
}


# Page. 52

![Page Image](https://bcdn.docswell.com/page/VEP6Y29V78.jpg)

Pattern Matching
オプショナルから値を抽出
// 意味的には Optional Binding と同等
if case let value? = optional {
print(value)
}


# Page. 53

![Page Image](https://bcdn.docswell.com/page/27V3GDMRJQ.jpg)

Pattern Matching
複数のオプショナルから値を抽出
// タプルを使ってまとめて変換が可能
if case let (a?, b?, c?)
= (optionalA, optionalB, optionalC) {
// すべてが nil でない場合に限り処理される
print(&quot;\(a), \(b), \(c)&quot;)
}


# Page. 54

![Page Image](https://bcdn.docswell.com/page/5JG38YG6EL.jpg)

Pattern Matching
値が範囲に含まれるか判定
// たとえば数値
if case 0 ..&lt; 100 = value {
print(&quot;contains&quot;)
}
// たとえば文字列
if case &quot;A&quot; ..&lt; &quot;G&quot; = string {
print(&quot;contains&quot;)
}


# Page. 55

![Page Image](https://bcdn.docswell.com/page/47Q59MX2EP.jpg)

条件指定


# Page. 56

![Page Image](https://bcdn.docswell.com/page/KE49XV6PJ1.jpg)

条件指定
if 文に where で条件を添える
// Swift 1.2 でも使えた記載方法
if let string = optionalString
where string.hasSuffix(&quot;.png&quot;) {
}


# Page. 57

![Page Image](https://bcdn.docswell.com/page/L71KN3VXEG.jpg)

条件指定
パターンマッチとの併用も可能
// 列挙子から値を抽出して条件判定
if case let .OSX(version) = platform
where version &gt; 10.10 {
}
// 複数のオプショナルを展開して条件判定
if case let (a?, b?, c?)
= (optionalA, optionalB, optionalC)
where a + b == c {
}


# Page. 58

![Page Image](https://bcdn.docswell.com/page/G7WD4PLKE2.jpg)

条件指定
guard でも使える
// 列挙子から値を抽出して条件判定
guard case let .OSX(version) = platform
where version &gt; 10.10 else {
}
// 複数のオプショナルを展開して条件判定
guard case let (a?, b?, c?)
= (optionalA, optionalB, optionalC)
where a + b == c else {
}


# Page. 59

![Page Image](https://bcdn.docswell.com/page/4JZG2KMN73.jpg)

条件指定
for でも使える
// nil 以外の要素で繰り返し
let optionals:[Int?]
for case let value? in optionals {
}
▶ ループの中で判定しなくて良い
▶ fratMap { $0 } でループさせなくて良い


# Page. 60

![Page Image](https://bcdn.docswell.com/page/YE6YVQN9JV.jpg)

条件指定
for でも使える
// nil 以外の繰り返しに条件まで付けられる
let optionals:[Int?]
for case let value? in optionals
where value &gt; 0 {
}
▶ 該当した要素だけが繰り返しの対象に


# Page. 61

![Page Image](https://bcdn.docswell.com/page/GE5GDR5DE4.jpg)

4/4
Extension


# Page. 62

![Page Image](https://bcdn.docswell.com/page/972Y8DGM7R.jpg)

Protocol Extension


# Page. 63

![Page Image](https://bcdn.docswell.com/page/DJYG62VPJM.jpg)

Protocol Extension
▶ プロトコルに既定の実装を添える仕組み
▶ 型エイリアスで実装条件を絞れる
extension Protocol {
func doSomething() {
// ここに実装を記載できる
}
}


# Page. 64

![Page Image](https://bcdn.docswell.com/page/V7NGZ8MME8.jpg)

Protocol Extension
既定の実装
extension CollectionType {
var count:Index.Distance {
}
return distance(
self.startIndex, self.endIndex)
}
▶ プロトコルで決められた機能で
実装を組み立てる


# Page. 65

![Page Image](https://bcdn.docswell.com/page/YJ9WZKNWJ3.jpg)

Protocol Extension
条件付きで拡張
extension CollectionType
where Generator.Element : IntegerType {
var sum:Generator.Element {
}
}
return self.reduce(0, combine: +)
▶ 型エイリアスをプロトコルで縛ると
それを想定した機能が使える
▶ 条件を満たす型だけに実装される


# Page. 66

![Page Image](https://bcdn.docswell.com/page/GJ8N1RKRED.jpg)

Protocol Extension
複数の条件で縛る
extension CollectionType where
Index : Streamable,
Generator.Element : IntegerType {
func printIndexOf&lt;S:OutputStreamType&gt;
(element:Generator.Element,
inout to stream:S) {
}
}
self.indexOf(element)?.writeTo(&amp;stream)


# Page. 67

![Page Image](https://bcdn.docswell.com/page/LJLPQKZ2ER.jpg)

Protocol Extension
同じ型であることを明記
extension CollectionType where
Generator.Element : IntegerType,
Index.Distance == Generator.Element {
var average:Generator.Element {
}
return self.reduce(0) { $0 + $1 } / self.count
var count:Index.Distance {
}
}
return distance(
self.startIndex, self.endIndex)


# Page. 68

![Page Image](https://bcdn.docswell.com/page/47M412V9EW.jpg)

Protocol Extension
自分自身を条件で縛る
extension CollectionType where
Self : Equatable,
Self : NillLiteralConvertible {
var isNull:Bool {
}
}
return self == nil


# Page. 69

![Page Image](https://bcdn.docswell.com/page/P7RWLM29E9.jpg)

Protocol Extension
明示的に型で縛る
extension CollectionType where
Generator.Element == String {
var lastPathComponents:String {
}
}
return self.map { $0.lastPathComponent }


# Page. 70

![Page Image](https://bcdn.docswell.com/page/PJXPWVD3EX.jpg)

Protocol Extension
既定の実装は上書き可能
extension MyProtocol {
var isValid:Bool {
}
}
return false
struct MyStruct : MyProtocol {
var isValid:Bool {
}
}
return true
採⽤用


# Page. 71

![Page Image](https://bcdn.docswell.com/page/3JKDVQXN7D.jpg)

Protocol Extension
継承して上書き可能
protocol MyProtoA {
}
protocol MyProtoB : MyProtoA {
}
extension MyProtoA {
func action() -&gt; Int {
}
}
extension MyProtoB {
func action() -&gt; Int {
}
採⽤用
}


# Page. 72

![Page Image](https://bcdn.docswell.com/page/LE3RMP5Z75.jpg)

Protocol Extension
親を呼ぶ、みたいなことはできない
extension MyProtoA {
func action() -&gt; Int {
}
}
extension MyProtoB {
func action() -&gt; Int {
}
}
return super.action()
&#039;super&#039; cannot be used outside of class members


# Page. 73

![Page Image](https://bcdn.docswell.com/page/8EDY6LD4EG.jpg)

Protocol Extension
キャストで呼び出し先を明記可能
extension MyProtoA {
func action() -&gt; Int {
}
}
extension MyProtoB {
func action() -&gt; Int {
}
}
return (self as MyProtoA).action() + 1


# Page. 74

![Page Image](https://bcdn.docswell.com/page/V7P6Y2XVJ8.jpg)

Type Extension


# Page. 75

![Page Image](https://bcdn.docswell.com/page/2JV3GDLREQ.jpg)

Type Extension
▶ 従来からある型の拡張方法
▶ Swift 2 から
ジェネリックパラメータで条件を絞れる
extension Array where Element : IntegerType {
func doSomething() {
}
}


# Page. 76

![Page Image](https://bcdn.docswell.com/page/5EG38YX67L.jpg)

Type Extension
条件をプロトコルで縛る
extension Optional where T : SignedNumberType {
var negative:Optional {
}
}
return self.map { -$0 }


# Page. 77

![Page Image](https://bcdn.docswell.com/page/4JQ59M827P.jpg)

Type Extension
型では縛れない
extension Optional where T == String {
}
Same-type requirement makes
generic parameter &#039;T&#039; non-generic


# Page. 78

![Page Image](https://bcdn.docswell.com/page/K749XV2PE1.jpg)

Type Extension
型の拡張は “既定の実装” ではない
extension MyStruct {
var isValid:Bool {
}
}
おさらい
return false
struct MyStruct {
var isValid:Bool {
}
}
return true
Invalid redeclaration of &#039;isValid&#039;


# Page. 79

![Page Image](https://bcdn.docswell.com/page/LJ1KN3MX7G.jpg)

後編
Coming Soon ?


# Page. 80

![Page Image](https://bcdn.docswell.com/page/GJWD4P3K72.jpg)

Swift 2.0 で変わったところ（前編）
▶ 制御構文
▶ Error Handling
▶ 詳細な条件指定
▶ Extension


