31
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-07-16

概要

アプリを作っているとネイティブと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のイベントをフックする
[WebViewシリーズ②] WebView内でJavaScriptのメソッドを操作する
[WebViewシリーズ③] WebViewは、ページ内のアンカーへリンクできない??
[WebViewシリーズ④] WebView(アプリ内)のリンクからiTunesが表示できない

ゆるふわにUIWebViewでJavaScriptイベントをひろってみる

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

31
22
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?