NSTrackingAreaの初期化


> When you create an NSTrackingArea object you must specify one or more options

NSTrackingAreaを初期化するときは、NSTrackingAreaOptionsを1つ以上渡す必要がありますが、このパラメータに制限があるようで、動かすのにちょっと苦労しました。Appleのリファレンスにもこの制限については記述が一切ありません。エラーメッセージでググってもあまり情報がなかったため、ここは一肌脱いでまとめようと思いました。

NSTrackingAreaOptionsは下記の通り10種類定義されています。[ドキュメント](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSTrackingArea_class/index.html#//apple_ref/c/tdef/NSTrackingAreaOptions)から抜粋しました。

```swift
struct NSTrackingAreaOptions : OptionSetType {
    init(rawValue rawValue: UInt)
    static var MouseEnteredAndExited: NSTrackingAreaOptions { get }
    static var MouseMoved: NSTrackingAreaOptions { get }
    static var CursorUpdate: NSTrackingAreaOptions { get }
    static var ActiveWhenFirstResponder: NSTrackingAreaOptions { get }
    static var ActiveInKeyWindow: NSTrackingAreaOptions { get }
    static var ActiveInActiveApp: NSTrackingAreaOptions { get }
    static var ActiveAlways: NSTrackingAreaOptions { get }
    static var AssumeInside: NSTrackingAreaOptions { get }
    static var InVisibleRect: NSTrackingAreaOptions { get }
    static var EnabledDuringMouseDrag: NSTrackingAreaOptions { get }
}
```

これだけだとなにもわからないのですが、[ソースコードのコメント](https://gist.github.com/08a0373f368304b0fe52
)から情報を得ることができました。(XcodeでNSTrackingAreaOptionsと書いて、`command + click` で飛んだ定義です。) 注意深くみてみると、Type of tracking area, When tracking area is active, Behavior of tracking area の3種類に分類され、最初の2種類は必須、最後の1種類はoptionalであることがなんとなくわかります。AppleのSDK全般に言えることですが、いろんなところにドキュメントが散乱していて困りますね。ちなみにこの制約を守らないと、ランタイムでクラッシュします。

まとめるとこんな感じのルールになっています。

Type of tracking area (どれか1つ以上必須)

- MouseEnteredAndExited
- MouseMoved
- CursorUpdate

When tracking area is active (どれか1つ以上必須)

- ActiveWhenFirstResponder
- ActiveInKeyWindow
- ActiveInActiveApp
- ActiveAlways

Behavior of tracking area (optional)

- AssumeInside
- InVisibleRect
- EnabledDuringMouseDrag

# エラーメッセージ

ググラビリティ向上のため、エラーになったときのメッセージと対応方法を残しておきます。

## trackingArea options 0x20 do not specify when the tracking area is active
When~ が含まれてないよと言っています。
.ActiveWhenFirstResponder,.ActiveInKeyWindow,.ActiveInActiveApp,.ActiveAlwaysのどれか１つ以上を指定してあげましょう。

このエラーになる例

```
        let options:NSTrackingAreaOptions = [. MouseEnteredAndExited]
        trackingArea = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil)
```


## trackingArea options 0x20 do not include a type

Type~ が含まれてないよと言ってます。
.MouseEnteredAndExited,.MouseMoved,.CursorUpdate のどれか１つ以上を指定してあげましょう。

このエラーになる例

```
        let options:NSTrackingAreaOptions = [.ActiveInKeyWindow]
        trackingArea = NSTrackingArea(rect: self.bounds, options: options, owner: self, userInfo: nil)
```

# NSTrackingAreaをNSViewに適用する
=== ここから追記しました ===
NSView.trackinAreasはread-onlyです。
実際にNSViewに適用するには下記のようにします。

```
    override func awakeFromNib() {
        super.awakeFromNib()
        configure()
    }

    func configure() {
        let options:NSTrackingAreaOptions = [
            .MouseEnteredAndExited,
            .MouseMoved,
            .CursorUpdate,
            .ActiveAlways
        ]
        let trackingArea = NSTrackingArea(rect: bounds, options: options, owner: self, userInfo: nil)
        addTrackingArea(trackingArea)
    }
```

`public var trackingAreas: [NSTrackingArea] { get }` をOverrideする方法では、`mouseEntered:` `mouseExited:` が呼ばれるようになりませんでした。

## 参考
http://stackoverflow.com/questions/11188034/mouseentered-and-mouseexited-not-called-in-nsimageview-subclass