値付き enum 入門、そして伝説へ #yhios #cocoa kansai

100
EZ-NET 熊谷友宏 http://ez-net.jp/ 2014.11.29 @ 横浜へなちょこiOS勉強会 #34.1 ~ そして伝説へ ~ 値付き enum 入門 2014.12.06 @ 第59回 Cocoa 勉強会関西

Upload: tomohiro-kumagai

Post on 12-Jul-2015

3.602 views

Category:

Technology


5 download

TRANSCRIPT

Page 1: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

EZ-NET 熊谷友宏 http://ez-net.jp/

2014.11.29 @ 横浜へなちょこiOS勉強会 #34.1

~ そして伝説へ ~値付き enum 入門

2014.12.06 @ 第59回 Cocoa 勉強会関西

Page 2: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

自己紹介

EZ-NET 熊谷友宏 @es_kumagai

Xcode 5 徹底解説

IP Phone 音でダイヤル 音で再配達ゴッド

いつもの電卓 for iPhone

いつもの電卓 for iPad

音で再配達

Page 3: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型

― いよいよ enum は究極形態へ ―

Page 4: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

普通の列挙型

列挙型

Page 5: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型定義

enum Basket {

case Empty

case Pineapple case Melon }

Swift

普通の列挙型

1. 限られた候補の中から値を採るデータ型 2. 意味で値をひとまとめにできる 3. 値を言葉で扱えるのでコードが明瞭に

Page 6: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型使い方

let value:Basket

switch value {

case .Pineapple: …

case .Melon: …

case .Empty: … }

Swift

普通の列挙型

Page 7: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

やや新しい列挙型

列挙型

Page 8: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型Raw 値の割り当て

やや新しい列挙型

1. 列挙子に内部的な値を付与 2. Objective-C では必ず Raw 値が設定される 3. Swift で Raw 値がない列挙子は具体値なし

enum Basket : Int {

case Empty = 0

case Pineapple = 1 case Melon = 2 }

定義

Page 9: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型列挙子から Raw 値を取得

let raw = Basket.Melon.rawValueRaw 値を取得

let value = Basket(rawValue: raw)!列挙子を生成

Raw 値から列挙子を生成

やや新しい列挙型

Page 10: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

まったく新しい列挙型

列挙型

Page 11: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型の新機能

1. 列挙型もオブジェクトプロパティやメソッドを実装可能

2. 整数値以外を Raw 値で使えるリテラル値から変換できる型を利用可能

3. 列挙子と合わせて値を持てる複数の値を自由に保有可能

まったく新しい列挙型

Page 12: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

1. 列挙型もオブジェクト

まったく新しい列挙型

Page 13: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

プロパティやメソッドを実装可能

まったく新しい列挙型

Page 14: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙子を文字列に変換するメソッド

enum Basket { case Empty, Pineapple, Melon

func toString() -> String? {

switch self {

case .Empty: return nil

case .Pineapple: return "Pineapple"

case .Melon: return "Melon" } }

メソッドの実装

まったく新しい列挙型

Page 15: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型の変数からメソッドを実行したり

let basket = Basket.Melon let string = basket.toString()

変数から実行

let string = Basket.Melon.toString()列挙子から実行

列挙子から直接メソッドを実行したり

まったく新しい列挙型

Page 16: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

?2. 整数値以外を Raw 値で使える

まったく新しい列挙型

Page 17: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

実際に使ってみると…

まったく新しい列挙型

Page 18: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

エラー

まったく新しい列挙型

『Raw 型がどのリテラルからも変換できません』

Page 19: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

リテラル値から変換できる型を 利用できるかと思えば …

まったく新しい列挙型

Page 20: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

利用できないものが多い

まったく新しい列挙型

Page 21: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

よくあるリテラル

1. 整数値リテラル … 0IntegerLiteralConvertible

2. 浮動小数点数値リテラル … 0.0FloatLiteralConvertible

3. 真偽値リテラル … trueBooleanLiteralConvertible

4. 文字列リテラル … "STRING"StringLiteralConvertible

[OK]

[OK]

[NG]

[OK]

まったく新しい列挙型

Page 22: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

これもリテラル

1. nil リテラル … nilNilLiteralConvertible

2. 配列リテラル … [ value, ... ]ArrayLiteralConvertible

3. 辞書リテラル … [ key : value, ... ]DictionaryLiteralConvertible

[NG]

[NG]

[NG]

まったく新しい列挙型

Page 23: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

使えるものに注目すれば …

1. 整数値リテラル 2. 浮動小数点数値リテラル 3. 文字列リテラル

まったく新しい列挙型

Page 24: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙子の値が…

文字列 でも良い

まったく新しい列挙型

Page 25: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Raw 値を文字列型にする…

enum Basket : String {

case Empty = ""

case Pineapple = "Pineapple" case Melon = "Melon" }

定義

まったく新しい列挙型

1. 内部的な値を文字列で付与 2. 列挙子と文字列値とが関連付けられる

Page 26: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Raw 値として文字列を取り出せる

let string:String = Basket.Melon.rawValueRaw 値の取得

let value:Basket? = Basket(rawValue: "Melon")列挙子の生成

文字列から列挙子を生成することも可能

まったく新しい列挙型

Page 27: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙子の型が… リテラルから変換 できれば良い

対応する

― それと等価判定もできること ―

まったく新しい列挙型

Page 28: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

1. 整数値リテラル IntegerLiteralConvertible

2. 浮動小数点数値リテラルFloatLiteralConvertible

3. 文字列リテラル StringLiteralConvertible

対応するリテラル

― 等価判定は Equatable ―

まったく新しい列挙型

Page 29: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

対応リテラルからの変換機能を実装クラスを浮動小数点数値リテラルに対応させる

class MyClass : FloatLiteralConvertible, Equatable {

// 変換イニシャライザ(浮動小数点数から) required init(floatLiteral value: FloatLiteralType) { } }

// 等価演算子 func ==(lhs:MyClass, rhs:MyClass) -> Bool {

return true }

プロトコルへ準拠

まったく新しい列挙型

Page 30: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型で独自クラスを使用浮動小数点数値リテラルに対応したクラス

enum Basket : MyClass {

case Empty = 0.0

case Pineapple = 1.0 case Melon = 1.1 }

列挙型の定義

まったく新しい列挙型

1. Raw 値の型に独自クラスを使用可能 2. Raw 値はリテラルで指定

Page 31: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

扱い方は普段どおり普通に使う分には Raw 値は意識しない

let basket:Basket = .pineapple

switch basket {

case .Pineapple: …

case .Melon: …

case .Empty: … }

列挙型の使用

Page 32: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Raw 値の独自型は

何時、使われるのかい つ

まったく新しい列挙型

Page 33: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

要点1列挙子を使う分には…

let basket:Basket = .pineapple

switch basket {

case .Pineapple: … case .Melon: … }

使用

1. 独自型は 全く使われない 2. 列挙子の操作では リテラル が使われる

まったく新しい列挙型

Page 34: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

要点2Raw 値を取得したとき…

1. 初めてインスタンスが生成される 2. 変換イニシャライザ が実行される 3. 列挙子が対応するリテラルが渡される

Basket.Melon.rawValue

MyClass(floatLiteral: 1.1)

MyClass

まったく新しい列挙型

Page 35: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

要点3Raw 値から列挙型を生成するとき…

1. Raw 値から インスタンスを生成 2. 列挙子を 順次 インスタンス化して比較 3. 戻り値は MyEnum? 型 4. 該当しない場合は nil を返す

まったく新しい列挙型

Page 36: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

MyClass(floatLiteral: 0.0) == obj

let obj = MyClass(floatLiteral: 1.0)

MyClass(floatLiteral: 1.1) == obj

MyEnum?

MyClass(floatLiteral: 1.0) == obj

case .Empty

case .Pineapple

case .Melon

MyEnum(rawValue: obj)

Page 37: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

要点4リテラルから列挙子を作るときも…

1. いったん 独自型に変換 される 2. 列挙子を 順次 インスタンス化して比較

MyEnum(rawValue: 1.0)

MyEnum(rawValue: MyClass(floatLiteral: 1.1))

MyEnum?

まったく新しい列挙型

Page 38: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

つまり独自型の Raw 値は…

1. 使い出すとハイコストその都度インスタンス化が行われる

2. 使わなければリテラルと同等列挙子自体は独自型では管理されない

― 列挙子とインスタンスを関連付ける的な役割 ―

まったく新しい列挙型

Page 39: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

?3. 列挙子と合わせて値を持てる

まったく新しい列挙型

Page 40: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型

― 値を持てる列挙型 ―

associated values

Page 41: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型定義

enum Basket {

case Empty

case Fruit(String) case Animal(String) }

Swift

― 列挙子にデータ型を添えて定義 ―

値付き列挙型

Page 42: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型列挙子を使う

let basket1 = Basket.Fruit("りんご") let basket2 = Basket.Animal("ライオン") let basket3 = Basket.Empty

宣言と代入

― 値付き列挙子には値を必ず添える ―

値付き列挙型

Page 43: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型値を加味した篩い分け

let basket:Basket

switch basket {

case .Fruit("みかん"): … case .Fruit("りんご"): … default: … }

分岐

― 列挙子と値での篩い分けが可能 ―

値付き列挙型

Page 44: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型大まかな篩い分け

let basket:Basket

switch basket {

case .Fruit: … case .Animal: … case .Empty: … }

分岐

― 列挙子だけでの篩い分けも可能 ―

値付き列挙型

Page 45: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型値を加味したり、しなかったり

let basket:Basket

switch basket {

case .Fruit("みかん"): … case .Fruit: … default: … }

分岐

― 自由に混在可能 ―

値付き列挙型

Page 46: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値付き列挙型値を取り出して利用する

let basket:Basket

switch basket {

case let .Fruit(fruit): println("\(fruit)!") }

分岐・値の取得

― 列挙子が一致したとき、その値を取り出す ―

値付き列挙型

Page 47: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

複数の値も付けられる

値付き列挙型

Page 48: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値が複数付いた列挙型定義

enum Basket {

case Empty

case Fruit(String, Int) case Animal(String, Int, Bool) }

Swift

― タプル型で列挙子の値を定義 ―

値付き列挙型

Page 49: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値が複数付いた列挙型値を取り出して利用する

let basket:Basket

switch basket {

case let .Fruit("りんご", price): println("\りんごは特売! \(price)円!")

case let .Fruit(name, price): println("\(name)が\(price)円!") }

分岐と各値の判定・取得

― 値を個別に取り出せる、どれか固定も可能 ―

値付き列挙型

Page 50: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値が複数付いた列挙型値を一括で取り出すことも可能

let basket:Basket

switch basket {

case let .Fruit(value): println("\(value.0)が\(value.1)円!") }

分岐と値の一括取得

― 値をタプル型で取り出せる ―

値付き列挙型

Page 51: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

値が複数付いた列挙型名前付きタプルも利用可能

switch basket {

case let .Fruit(value): println("\(value.name)が\(value.price)円!") }

使用

enum Basket {

case Empty

case Fruit(name: String, price: Int) }

定義

値付き列挙型

Page 52: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな 値付き列挙型

― 汎用的な値を持つ ―

Page 53: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックとはGenerics

汎用的に型を扱う仕組み― 型に縛られないコードが書ける ―

func makePair<T,U>(first:T, second:U)->(T,U) {

return (first, second) }

ジェネリック関数

ジェネリックな値付き列挙型

Page 54: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな値付き列挙型定義

enum Basket<Type> {

case Empty

case Fruit(Type) case Animal(String) }

Swift

ジェネリックを値に持つ列挙型で 複数の値付き列挙子を定義できない

仕様上 N

G

ジェネリックな値付き列挙型

Page 55: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな値付き列挙型定義

enum Basket<Type> {

case Empty

case Nandemo(Type) }

Swift

― 列挙子が採る値の型を汎用化 ―

ジェネリックな値付き列挙型

Page 56: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

1. 渡した値に応じて列挙型が決まる 2. 宣言以降は値の型を変えられない 3. あくまでもコードの汎用化が目的

ジェネリックな値付き列挙型型に縛られない列挙型の使用

let basket1:Basket<String> = Basket.Nandemo("りんご")

let basket2:Basket<Int> = Basket.Nandemo(1000)

宣言と代入

ジェネリックな値付き列挙型

Page 57: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな値付き列挙型扱い方は通常と同じ

switch basket {

case let .Nandemo(value): …

case .Empty: … }

判定

― 値の型は宣言時に決めた型 ―

ジェネリックな値付き列挙型

Page 58: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ところで…

ジェネリックな値付き列挙型

Page 59: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな値付き列挙型

enum Basket<Type> {

case Empty case Nandemo(Type) }

この列挙型と、

似たコンセプトの列挙型…

enum Optional<T> {

case None case Some(T) }

この列挙型と。

ジェネリックな値付き列挙型

Page 60: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ジェネリックな値付き列挙型

enum Optional<T> { case None case Some(T) }

どこかで見覚えのある列挙型

Page 61: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

そして伝説へ…

Page 62: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional<T>

― nil を持てる型 ―

そして伝説へ…

Page 63: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional<T>オプショナルとは?

1. 任意の値を格納できる型 2. 値の型は宣言時に決定 3. 値がない状態を “nil” で表現可能 4. Swift 言語の重要な機能

そして伝説へ…

Page 64: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Swift の Optional って

String?

そして伝説へ…

Page 65: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

シンタックスシュガー― 簡単に書くための構文 ―

Page 66: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

is

String?

Optional<String>

シンタックスシュガー

― 明示的な扱いが必要な nil 許容型 ―

Page 67: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional<T>Swift で定義されている

そして伝説へ…

Page 68: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional<T>定義から見る特徴

1. ジェネリックな値付き列挙型 2. ある値 .Some(T) と何もない値 .None を採る

3. 引数名なしで値を採るイニシャライザinit(_ some:T)

4. nil リテラルから変換可能NilLiteralConvertible

そして伝説へ…

Page 69: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

シンタックスシュガー ということは

ジェネリックな値付き列挙型

Page 70: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let str1:String? = "STRING" let str1:String? = nil

let str2:Optional<String> = .Some("STRING") let str2:Optional<String> = .None

嘘のような本当の話この2つは同じことを表現

シンタックスシュガー

シンタックスシュガー

列挙型による実装

Page 71: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// Optional<T> に T? のときと同じ表現で代入 let str1s:Optional<String> = "STRING" let str1n:Optional<String> = nil

// String? に enum Optional<T> の書式で代入 let str2s:String? = .Some("STRING") let str2n:String? = .None

// String? を Optional<T> のイニシャライザで生成 let str3s:String? = Optional<String>("STRING") let str3n:String? = Optional<String>()

シンタックスシュガーと列挙型の混在

表現は違っても値は同じ同じことなので混在も可能

シンタックスシュガー

Page 72: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

実際の動きを知ると Optional が分かりやすくなる

シンタックスシュガー

Page 73: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// 型の最後に「?」を付ける let str:String? = "STRING"

// 列挙型 Optional.Some の値として指定する let str2 = Optional.Some("STRING")

// Optional<T> のイニシャライザでも良い let str2 = Optional("STRING")

値を Optional でラップするOptional 型に値を設定

シンタックスシュガー

シンタックスシュガー

列挙型による実装

Page 74: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// 型の最後に「?」を付けた変数に nil を代入する let str:String? = nil

// Optional<T>.None を代入する(要・型の明示) let str2 = Optional<String>.None

// Optional<T> のイニシャライザでも良い let str2 = Optional<String>()

Optional に nil を代入するOptional 型に nil を設定

シンタックスシュガー

シンタックスシュガー

列挙型による実装

Page 75: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

if str != nil {

} else {

}

switch str { case .Some: … case .None: … }

値が nil かを判定する値があるかないかを if で判定

シンタックスシュガー

シンタックスシュガー

列挙型による実装

Page 76: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

if let value = str {

} else {

}

switch str { case let .Some(value): … case .None: … }

値が nil かを判定するOptional Binding で値を取得

シンタックスシュガー

シンタックスシュガー

列挙型による実装

Page 77: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str!

var value:String

switch str {

case let .Some(v): value = v

case .None: abort() }

Optional から値を取り出す強制アンラップ

シンタックスシュガー

列挙型による実装

シンタックスシュガー

Page 78: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str ?? "DEFAULT"

Optional から値を取り出すnil 結合演算子(右辺が nil 非許容のとき)

シンタックスシュガー

var value:String

switch str {

case let .Some(v): value = v

case .None: value = "DEFAULT" }

列挙型による実装

シンタックスシュガー

Page 79: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str ?? Optional("DEFAULT")

Optional から値を取り出すnil 結合演算子(右辺が nil 許容のとき)

シンタックスシュガー

var value:String?

switch str {

case let .Some: value = str!

case .None: value = Optional("DEFAULT") }

列挙型による実装

シンタックスシュガー

Page 80: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str?.hashValue

Optional から値を取り出すOptional Chaining で値を取得

シンタックスシュガー

var value:Int?

switch str {

case let .Some(v): value = v.hashValue

case .None: value = nil }

列挙型による実装

シンタックスシュガー

Page 81: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

! も ? も ?? も

バリエーション

nil かどうかで「どうするか」 が少し違うだけ

Page 82: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

シンタックスシュガーのおかげで Optional を簡単に扱える

シンタックスシュガー

― switch 文を省略できる ―

Page 83: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ちなみに

Page 84: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional<T> には func map<U>(f: (T)->U) -> U?

1. 値が nil なら nil を返す 2. 値が nil でなければ、引数で渡されたクロージャの実行結果をラップして返す

Page 85: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str?.hashValue

Optional から値を取り出すOptional<T>.map<U> メソッドで実行

シンタックスシュガー

// いちばん短い書き方 let value = str.map { $0.hashValue }

// 省略しない書き方 let value = str.map({ (value:String) -> Int in

return value.hashValue })

Optional 型による実装

シンタックスシュガー

Page 86: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

もうひとつ

Page 87: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ImplicitlyUnwrappedOptional<T>

― Optional の姉妹品 ―

Page 88: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

isString!

ImplicitlyUnwrappedOptional<String>

シンタックスシュガー

― 暗黙的にアンラップされる nil 許容型 ―

Page 89: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// 型の最後に「!」を付ける let str:String! = "STRING"

シンタックスシュガー

// 列挙型 .Some の値として指定する let str2 = ImplicitlyUnwrappedOptional.Some("STRING")

列挙型による実装

ImplicitlyUnwrappedOptional値のラップは Optional と同等

シンタックスシュガー

Page 90: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// 型の最後に「!」を付けた変数に nil を代入する let str:String! = nil

// .None を代入する(要・型の明示) let str2 = ImplicitlyUnwrappedOptional<String>.None

シンタックスシュガー

ImplicitlyUnwrappedOptionalnil の設定は Optional と同等

シンタックスシュガー

列挙型による実装

Page 91: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

if str != nil {

} else {

}

switch str { case .Some: … case .None: … }

シンタックスシュガー

ImplicitlyUnwrappedOptional値の nil 判定は Optional と同等

シンタックスシュガー

列挙型による実装

Page 92: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

Optional Binding は存在しない

シンタックスシュガー

ImplicitlyUnwrappedOptional

― 暗黙アンラップが基本 ―

( if let v = str )

Page 93: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str! // 明示アンラップ let value:String = str // 暗黙アンラップ

var value:String

switch str {

case let .Some(v): value = v

case .None: abort() }

列挙型による実装

シンタックスシュガー

アンラップは型が明確なら暗黙的に実施ImplicitlyUnwrappedOptional

シンタックスシュガー

Page 94: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

let value = str ?? "DEFAULT"

nil 結合演算子は Optional と同等(nil 非許容)

シンタックスシュガー

var value:String

switch str {

case let .Some(v): value = v

case .None: value = "DEFAULT" }

ImplicitlyUnwrappedOptional

列挙型による実装

シンタックスシュガー

Page 95: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

// 結果は Optional<T> で得られる let value = str ?? Optional("DEFAULT")

シンタックスシュガー

var value:String?

switch str {

case let .Some: value = str!

case .None: value = Optional("DEFAULT") }

nil 結合演算子は Optional と同等(nil 許容)ImplicitlyUnwrappedOptional

列挙型による実装

シンタックスシュガー

Page 96: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

//「?」はなく即時アンラップ(nil なら強制終了) let value = str.hashValue

シンタックスシュガー

var value:Int

switch str {

case let .Some(v): value = v.hashValue

case .None: abort() }

Optional Chaining は無くて暗黙アンラップImplicitlyUnwrappedOptional

列挙型による実装

シンタックスシュガー

Page 97: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

ImplicitlyUnwrappedOptional も Optional と僅かに違うだけ

シンタックスシュガー

1. 明示的/暗黙的アンラップ 2. Optional Binding の有無 3. Optional Chaining の有無

str!

if let v = str

str?.hashValue

Page 98: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

仕組みを意識すると Optional って意外とシンプル

― 列挙型のシンタックスシュガー ―

Page 99: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

列挙型の基礎から Swift での実用例までのお話でした

値付き enum 入門

以上

Page 100: 値付き Enum 入門、そして伝説へ #yhios #cocoa kansai

『値付き enum 入門』

1. 普通な列挙型case Pineapple, Melon, Empty

2. Raw 値を持てる列挙型enum Basket : MyClass {

3. 列挙子ごとに値を持てる列挙型case Fruit(String)

4. ジェネリックな値付き列挙型enum Basket<T> {

5. Optional も列挙型enum Optional<T> {