iOS のナウい機能 3 つの活用方法に思いを巡らせる


iPhone や iOS がアップデートされる度に，新機能が追加されていきますね．とはいっても，Apple はあくまでもベーシックな機能を提供しているだけで，それがどれだけユーザにインパクトを与えられるかは，サードパーティのアプリ内で我々がどれだけ活用できるか次第であると言えます．

今回は，比較的最近追加された 3 つの機能 (気圧センサ，3Dtouch，タッチ面積) の Swift での実現方法と，その活用方法の可能性について書いてみようと思います．

## 気圧センサ (iPhone6 ~)

### 実装方法

```CMAltimeter``` を用いて気圧を取得することができます．

```swift
import CoreMotion

class ViewController: UIViewController {

    let altimeter = CMAltimeter()
    
    ...

    func getPressure() {
        guard CMAltimeter.isRelativeAltitudeAvailable() else { return }
        altimeter.startRelativeAltitudeUpdatesToQueue(NSOperationQueue.mainQueue(), withHandler: {data, error in
            print(error == nil ? "pressure: \(Double(data!.pressure)*10) hPa" : error)  // 気圧取得
        })
    }
}

```

### 活用方法

気圧の魅力は何と言っても，緯度経度の 2 次元に加え，__高さ__ の考慮が可能となるところでしょう．現地点の気圧だけでは絶対的な高さの取得はできませんが (※1, ※2)，相手と同じ場所にいるのかの判定などには利用できます．

例えば LINE のふるふるは，GPS とふるタイミングでペアリングしていると言われています．なので，同じビルの 1F と 10F にいる人がたまたま同時にふり始めると GPS が近いためペアリングしてしまいます．しかし 1F と 10F では気圧は大きく差があるので，気圧を考慮することでそれらをはじくことができます．また，Waaaaay! などの待ち合わせアプリでも，同程度の気圧の場所にいるかを確認することで，本当に出会えているかが分かるようになりますね．

__※1__ 取得開始時を 0 とした相対高度は ```data!.relativeAltitude``` で取得できます．

__※2__ 余談ですが，絶対高度 ```h``` は以下の式で求めることができます．
![20150323235856.png](https://qiita-image-store.s3.amazonaws.com/0/7113/5f198993-856a-0cfe-43f2-07b62d0d5562.png "20150323235856.png")
すなわち，現在地の気温 ```T0```，現在地の気圧 ```P0```，海面気圧 ```P``` が分かると，原理的には絶対高度を求めることができます．今後 iPhone が気圧センサだけではなく気温センサも搭載し，かつ OpenWeatherMap API などで海面気圧を正確に取得することができれば，絶対的な高さの取得は実現可能なように思います．

## 3Dtouch (iPhone6s ~)

### 実装方法

```touchesBegan``` や ```touchesMoved``` 内で ```UITouch``` の ```force``` メソッドを呼び出すことで，3Dtouch の圧力を取得できます．

```
class ViewController: UIViewController{

    ...

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesBegan(touches, withEvent: event)
        print("force: \(touches.first!.force)")  // 開始時なので常に 0.0 が返ってくる
    }
    
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesMoved(touches, withEvent: event)
        print("force: \(touches.first!.force)")
    }

}
```

### 活用方法

3Dtouch によって，1 つのコンポーネントに複数の機能を持たせやすくなりました．これまでもタップと長押しなど，1 つのコンポーネントが複数のジェスチャーを兼ね備えることはできましたが，たいていの場合シンプルさを欠き，優れたユーザビリティを保つのは難しかったように思います．

3Dtouch は，画面に奥行きを与えることでジェスチャーを 3 次元に拡張しています．そのため，従来の画面内でのジェスチャーと比べて「浅さ」「深さ」といった直感的な対応が取りやすく，アフォーダンスの形成が容易になりました．

例えば，カメラをタップで起動，ムービーを 3Dtouch で起動といったように，「機能のリッチさ」を 浅 ↔ 深 に対応させる，あるいは「一発検索」「条件検索」といったように「機能の詳細さ」を 浅 ↔ 深 に対応させるといったことが考えられます．うまく利用することができると，ユーザビリティを損なうことなく類似のコンポーネントを 1 つにまとめることができるのではないでしょうか．

## タッチ面積 (iOS8 ~)

### 実装方法

3Dtouch と同様です．```touchesBegan``` や ```touchesMoved``` 内で ```UITouch``` の ```majorRadius``` メソッドを呼び出します．

```
class ViewController: UIViewController{

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        view.multipleTouchEnabled = true  // マルチタッチしたい場合は設定
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesBegan(touches, withEvent: event)
        print("majorRadius: \(touches.first!.majorRadius)")
    }
    
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        super.touchesMoved(touches, withEvent: event)
        print("majorRadius: \(touches.first!.majorRadius)")
    }

}
```

### 活用方法

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/wfk4Czg_0rU/0.jpg)](http://www.youtube.com/watch?v=wfk4Czg_0rU)

上の動画のような，筆圧の取得などがメジャーな利用方法として挙げられます．しかし，タッチ面積は，スマホの画面上で何かをするといったものだけでなく，スマホを何かの手段として利用するものに対しても可能性が開けています．先日バズった，スマホを胸にはさんでカップ数を測定するアプリ ChiChi なんかは，タッチ面積をうまく利用している例だと思います．

また，気圧センサや 3Dtouch はデバイス依存ですが，タッチ面積は OS 依存であり，iOS8 以上だと利用できるので導入がしやすいです．