Swift Tips


SwiftのTipsを書きます。

**追記**
Tips その２にするつもりだったものを投稿しました。
Tipsっぽくなくなってしまったので当記事のタイトルからその１を外しました。
[クロージャのメモリ管理について](http://qiita.com/_tid_/items/df7f1b76f156bd758c1a)

## enum

### Associated values enum

例えば下記のようなC言語の構造体と同じ意味合いのデータ構造はSwiftだと型情報と値をまとめられます。

```c
enum Type {
    UNDEFINED,
    BOOLEAN,
    NUMBER,
    STRING
}

struct Variant {
    Type   type;
    int    boolval;
    double floatval;
    char * stringval;
}
```

```swift
enum Variant {
    case Bool(Swift.Bool)
    case Number(Double)
    case String(Swift.String)
}
```


#### Result
よく使われるResult型はこれとジェネリクスを組合せて、成否とそれに紐づく任意の情報をまとめています。

```swift
enum Result<T, U:ErrorType> {
   case Success(T)
   case Failure(U)
}
```

参考：[Result.swift](https://github.com/Alamofire/Alamofire/blob/master/Source/Result.swift) - GitHub Alamofire

## struct
### 組合せ可能なオプション(OptionSetType)
```swift
struct MyOption: OptionSetType {
    private(set) var rawValue: UInt
    init(rawValue: UInt) { self.rawValue = rawValue }
    
    static let OptionA = MyOption(rawValue: 1)
    static let OptionB = MyOption(rawValue: 2)
    static let OptionC = MyOption(rawValue: 4)
}

// OptionA と OptionC の組合せ
let opt: MyOption = [.OptionA, .OptionC]
```

## typealias
### 別名をつける

例えば何かしらの処理の完了時に呼び出されるクロージャがある場合、`typealias` を使うと下記のように書けます。

```swift
typealias CompleteHandler = (String, NSError) -> Void

func hoge(completion: CompleteHandler) {
    // ...
}

func fuga(completion: CompleteHandler) {
    // ...
}
```

typealiasを使わないとこうなります。引数名で意味は通りますが、
後から"クロージャの第二引数をOptionalにしたい"と思った時に変更漏れを起こすかもしれません。

```swift
func hoge(completion: (String, NSError) -> Void) {
    // ...
}

func fuga(completion: (String, NSError) -> Void) {
    // ...
}
```

クロージャに限らず型に意味を持たせられる時は `typealias` で別名を与えましょう。

### Associated Types

下記のプロトコルを見てください。
`typealias`を定義していますがどの型にも紐づけられていません。

```swift
protocol Container {
    typealias ItemType
    mutating func append(item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}
```

これを関連型(Associated Types)といい、プロトコルを実装するクラスで紐づけを行います。
この時、Genericを使うこともできます。もちろん使わなくてもいいです。
`typealias ItemType` はどこいったの？と思いますがItemTypeが使われていた箇所を
すべて型指定に変えることで省略可能です。

```swift
struct Stack<Element>: Container {
    // original Stack<Element> implementation
    var items = [Element]()
    mutating func push(item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
    // conformance to the Container protocol
    mutating func append(item: Element) {
        self.push(item)
    }
    var count: Int {
        return items.count
    }
    subscript(i: Int) -> Element {
        return items[i]
    }
}
```

何が嬉しいのかですが、型の制約を作れます。

```swift
func allItemsMatch<
    C1: Container, C2: Container
    where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
    (someContainer: C1, _ anotherContainer: C2) -> Bool {
    // 省略...
}
```

`SequenceType` プロトコルなどで使われているので知っておくと実装する時に捗ります。

参照：[Associated Types](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Generics.html#//apple_ref/doc/uid/TP40014097-CH26-ID189) ーThe Swift Programming Language


## String
### 文字列を複数行に分けて書く
```swift
let text = "hoge\nfuga\nfoo\nbar"
```

```swift
let text = [
    "hoge",
    "fuga",
    "foo",
    "bar",
].joinWithSeparator("\n")
```

## print
### デバッグモードの時だけ出力する
```swift
func print(items: Any..., separator: String = " ", terminator: String = "\n") {
    #if DEBUG
        Swift.print(items[0], separator:separator, terminator: terminator)
    #endif
}
```

*デバッグモードのみで有効になる `DEBUG` の定義が必要です。*

### 終端文字の指定
引数 `terminator:` で指定します。

```swift
// 改行させない
print("HOGE", terminator: "")
```