Webのアプリ対応がめんどくさかった時の話

とあるWebサービスのiPhoneアプリクライアントを作っていた時の話です
JavaScriptとObjective-Cを連携するにはdocument.locationをいじればいいのですが、この処理を今あるWebサイト全体に入れるのはかなり手間ですしリンクの処理を上書きしたい時はブラウザの挙動が変わってしまうのでアプリ用のWebサイトを別途用意する必要がありました(´・ω・`)
そこでブラウザから普通に見れるサイトがアプリを通して見るといろんな仕掛けが顔をだすような仕組みを作りたかったのでUIWebViewを継承して作ってみました。

ClassHookWebView
詳しい使い方はREADME.mdの方に書いたのでここでは簡単な使い方と仕組みについて解説したいと思います

特徴

  • UIWebViewと同じように使える(Delegateも使える)
  • Webサイト側はタップの時にアプリのメソッドを呼び出したいDOMにクラスをつけるだけ
  • <a>タグの挙動はブラウザから見ても変わらない

使い方

Webサイト側

タップの時にアプリのメソッドを呼び出したいDOMにクラスをつける

終わり\(^o^)/

アプリ側

ClassHookWebViewをUIWebViewと同じように初期化して配置する

ロードする前にタップを取得したいDOMについているクラスとタップ時に実行するメソッドを登録する

終わり\(^o^)/

Example

詳しい動作はClassHookWebViewからクローンして付属しているXCodeプロジェクトを実行すると確認できます

仕組み

どうやって動いているのかというととても単純でロードが終わったら特定のクラスが付いているDOMをとってきてJavaScriptで動作を書き換えてやってます。UIWebViewにはstringByEvaluatingJavaScriptFromString:という便利なメソッドがあって現在表示されているページ上で任意のJavaScriptを実行することができます。これを使って

  • href属性の値を取得
  • data-href属性に入れなおす
  • href属性にはjavascript:void(0)を入れる
  • addEventListenerでclickイベントの時にdocument.locationを書き換えるように設定

という処理をDOM毎に行っています。
href属性から値をとっているのは<a>タグの処理を上書きしたかったらで<div>タグであっても無理やりクラスとhref属性を指定してやれば値のやり取りをすることもできますw

Delegateはセッターで別オブジェクトに設定するようにしてUIWebViewDelegate Protocolで指定されているメソッドを全部上書きして設定したオブジェクトに流すようにしています!
大体の流れはこんな感じで更に詳しくは是非コードを読んでみてください(^O^)/
ClassHookWebView

ひろせ


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です