[WebViewシリーズ①]  WebViewのイベントをフックする

# 概要
アプリを作っているとネイティブとWebViewが混在して実装することが多いと思います。
特に、Web版からアプリを作りたいという時に多いです。
今回は、WebViewのイベントをフックして、ネイティブで処理する際のメモを共有します。

# やるべきこと
1. WebViewにネイティブへリダイレクトする処理を追加する。
2. ネイティブにWebViewからのリダイレクトされたときの受け口を追加する。

## 今回例示するシーン
ログイン後にWebからトークンIDを取得する。
今回は、WebViewの説明は割愛します。

## 1. WebViewにネイティブへリダイレクトする処理を追加する。
WebViewでログインボタンを押下した際に、
ネイティブにリダイレクトする処理を追加する必要があります。

例)
```
header("Location: sdt://login?tokenID=1234567890")
```

#### WebViewからネイティブへフックするときのインタフェースについて
sdt://login?tokenID=1234567890

| キー |  説明  | 
|---------| -------------| 
| sdt:// | URLスキーム       | 
| login | アクション名         | 
| tokenID | トークンID（パラメタ） | 

## 2. ネイティブにWebViewからのリダイレクトされたときの受け口を追加する。

### 実装のポイント
WebViewのshouldStartLoadWithRequestの戻り値に下記の値を返す

①URLスキームが「http」 or 「https」の場合は、「true」を返す
②URLスキームが「sdt」の場合は、「false」を返す

falseを返すと、処理を中断するため、
このタイミングでWebViewからネイティブへフックされる。

### 参考ソースコード

```:UIViewController.swift
//MARK: - UIWebViewDelegate
extension ViewController: UIWebViewDelegate {
    
    func webView(webView: UIWebView, shouldStartLoadWithRequest
        request: NSURLRequest,
        navigationType: UIWebViewNavigationType) -> Bool {
        
        if let scheme = request.URL?.scheme where scheme.hasPrefix("http") {
            return true
        }
        
        if let action = request.URL?.description, let query = request.URL?.query {
            let queryDic = QueryParser.queryDictionary(query)
            
            //ログインボタンが押下された時の処理を行う
            if action.hasPrefix("sdt://login") {
                print(queryDic["tokenID"])
            }
        }
        return false
    }
}
```

### パラメタの受け取り
今回パラメタの受け取りは、下記のようなクラスを作成しました。

```:QueryParser.swift
import Foundation

class QueryParser {
    
    class func queryDictionary(query: String) -> [String:String]{
        
        var querys = [String: String]()
        let pairs = query.componentsSeparatedByString("&");
        
        for pair in pairs {
            let elements = pair.componentsSeparatedByString("=")
            let key = elements[0].stringByRemovingPercentEncoding
            let value = elements[1].stringByRemovingPercentEncoding
            
            if let key = key, value = value {
                querys[key] = value
            }
        }
        return querys
    }
}
```

### パラメタが複数ある場合も確認しておきます。

```:QueryParserTests.swift
import XCTest
@testable import WebViewBridge

class QueryParserTests: XCTestCase {

    override func setUp() {
        super.setUp()
    }
    
    override func tearDown() {
        super.tearDown()
    }

    func testQuery() {
        
        let query = QueryParser.queryDictionary("tokenID=12345678&name=sdt&age=6&numbers=40")
        XCTAssertEqual(query["tokenID"], "12345678")
        XCTAssertEqual(query["name"], "sdt")
        XCTAssertEqual(query["age"], "6")
        XCTAssertEqual(query["numbers"], "40")
    }
}
```

# まとめ
1. WebViewにネイティブへリダイレクトする処理を追加する。
2. ネイティブにWebViewからのリダイレクトされたときの受け口を追加する。

# こちらも合わせて読んでください♥
[[WebViewシリーズ①]　WebViewのイベントをフックする](http://qiita.com/eKushida/items/a1679e2f438d3fa83c18)
[[WebViewシリーズ②]　WebView内でJavaScriptのメソッドを操作する](http://qiita.com/eKushida/items/055dc36119757b2c304e)
[[WebViewシリーズ③]　WebViewは、ページ内のアンカーへリンクできない？？](http://qiita.com/eKushida/items/dd91615c68f3bd5abdd1)
[[WebViewシリーズ④]　WebView（アプリ内）のリンクからiTunesが表示できない](http://qiita.com/eKushida/items/f7f7195ca0f12b25bca1)

[ゆるふわにUIWebViewでJavaScriptイベントをひろってみる](http://qiita.com/nnsnodnb/items/27fd7c1ca2f8e24ec9c7)

誤り等ございましたら、ご指摘頂ければ幸いです。