25
Enumはデキる子 AKIBA.swift #02 ~ case .Success(let value): ~ Takaaki Tanaka

Enumはデキる子 ~ case .Success(let value): ~

Embed Size (px)

Citation preview

Enumはデキる子

AKIBA.swift #02

~ case .Success(let value): ~

Takaaki Tanaka

About Me• 田中 孝明 (Takaaki Tanaka)

• クラスメソッド株式会社

• @kongmingtrap

• iOS Developer (Swift / Objective-C)

• GyazSquare / GitHub

Agenda

• Enumについて

• Enumについて

• Enumについて

Enum

• プログラム上、意味のある値を列挙して定義することができる

• Objective-C → Swiftで大幅に強化された

• むしろほぼ別物と言っても過言ではない

Enum

enum { IMTypeCute, IMTypeCool, IMTypePassion };

• C/C++ Style 😨

Enum

typedef NS_ENUM(NSUInteger, IMType) { IMTypeCute, IMTypeCool, IMTypePassion };

• Objective-C (Cocoa) Style 😨

Enum

typedef NS_OPTIONS(NSUInteger, IMType) { IMTypeCute = 1UL << 0, IMTypeCool = 1UL << 1, IMTypePassion = 1UL << 2, IMTypeAll = (IMTypeCute | IMTypeCool | IMTypePassion) };

• Objective-C (Cocoa) Style 😨

SwiftでのEnumの特徴• 第一級オブジェクト(first-class type)

• RawValue(String / Int / Float)

• ネスト定義ができる

• 独自のメソッドを定義できる

• Caseにtupleが使える

第一級オブジェクト (first-class type)

• 変数に格納可能

• データ構造に格納可能

• それ自体が独自に存在できる

• 関数のパラメータとして渡すことができる

• 関数の戻り値として返すことができる

RawValue

enum PeachBoySlave: Int { case Dog case Monkey case Bird }

• Swift Style 😋

print(PeachBoySlave.Bird.rawValue) // 2

RawValue

enum PeachBoySlave: String { case Dog = "Dog" case Monkey = "Monkey" case Bird = "Bird" }

• Swift Style 😋

print(PeachBoySlave.Bird.rawValue) // Bird

RawValue

guard let slaveType = PeachBoySlave(rawValue: "Bird") else { return }

• RawValueに存在すればEnumを実体化できる

print(slaveType) // Bird

ネスト

enum PeachBoySlave: String { case Dog case Monkey case Bird enum Actor { case Grandpa case Grandma } }

• Enumの定義内にさらにEnumを定義することが可能

独自のメソッド定義

enum PeachBoyEnemy { case Oni case Boss func encount() { print("Enemy") } }

• Enumにも関数を定義することができる

計算型プロパティ定義

enum PeachBoyEnemy { case Oni case Boss … var count: Int { switch self { case Oni: return 10 case Boss: return 1 } } }

• 計算型プロパティのみ定義することができる

Tuple

enum PeachBoyEnemy { case Oni(String, String) case Boss func encount() { switch self { case Oni(let number, let colorName): print(Number + ": Oni " + colorName) case Boss: print("Boss") } } }

• CaseにTupleを指定することで異なる構造を持つメンバーを定義することができる

Tuple

let oni: PeachBoyEnemy = .Oni("1", "Red") oni.encount()

• CaseにTupleを指定することで異なる構造を持つメンバーを定義することができる

1: Oni Red

AlamofireのRouterでの応用enum Router: URLRequestConvertible { case ItemSearch([String : AnyObject]) var URLString: String { let baseURL = "http://shopping.yahooapis.jp/ShoppingWebService/V1/json/"

switch self { case ItemSearch: return baseURL + "itemSearch" } } var Method: Alamofire.Method { switch self { case .ItemSearch: return .GET } } var URLRequest: NSMutableURLRequest { let request = NSMutableURLRequest(URL: NSURL(string: URLString)!) switch self { case .ItemSearch(let parameters): return Alamofire.ParameterEncoding.URL.encode(request, parameters: parameters).0 } }

AlamofireのRouterでの応用enum Router: URLRequestConvertible { case ItemSearch([String : AnyObject]) …

var URLRequest: NSMutableURLRequest { let request = NSMutableURLRequest( URL: NSURL(string: URLString)!) switch self { case .ItemSearch(let parameters): return Alamofire.ParameterEncoding. URL.encode( request, parameters: parameters).0 } }

ジェネリクスの応用

public enum Result<Value, Error: ErrorType> { case Success(Value) case Failure(Error) }

• tubleとジェネリクスを指定することで成功時、失敗時も値を返すEnumを定義することができる

ジェネリクスの応用

func resultWithCode(code: Int?) -> Result<Int, NSError> { guard let unwrapedCode = code else { return .Failure(NSError(domain: "MyApp", code: 0, userInfo: nil)) } return .Success(unwrapedCode) }

• 戻り値をResultにした場合

ジェネリクスの応用

let result = resultWithCode(200) switch result { case .Success(let code): print(code) case .Failure(let error): print(error) }

• 値はパターンマッチで比較することができる

実際に使うケースAlamofire.request(Router.ItemSearch(parameters)) .responseJSON { response in switch response.result { case .Success(let value) : let json = JSON(value) guard let resultSet = json["ResultSet"].dictionary else { return } guard let resultsOfOnePage = resultSet["0"]?.dictionary else { return } guard let results = resultsOfOnePage["Result"]?.dictionary else { return } self.items = results.keys.map { Item(json: results[$0]!) } case .Failure(let error) : print("error: \(error)") } self.tableView?.reloadData() self.refreshControl?.endRefreshing() }

実践編

Modern Core Data by try! Swift

まとめ

• Objective-Cからの強化されている

• 過去の遺産を型安全なプログラムへ生まれ変わらせるヒントになる

• ジェネリクスと応用すると値の比較処理も簡潔に記述できる