ページ

2015年9月26日土曜日

iOSのUIWebView + AngularJSで画面遷移


以前にUIWebView+AngularJSで軽く動作させてみましたが、
今回は画面遷移をやってみようと思います。

構成としては
  • トップメニュー画面
  • サブ画面
  • メイン画面
で、トップメニュー画面とサブ画面がUIWebView上のHTMLで表示、
メイン画面を通常のViewで実装してみたいと思います。
・イメージ図

独自URLスキームの作成


実装するアプリ専用のURLスキームを作成し、そのURLスキームで
リクエストが来た場合のみ処理を行うようにしたいと思います。
URLスキームとは
URLスキームはhttp://hogehogeのhttpを差します


前回WebViewが新たなフレームをロードする時にハンドリングする
メソッドをオーバーライドしました
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
      return true
    }
今回はここでNSURLRequestからURLを取得し、作成する独自スキームであれば 画面遷移を行うようにしたいと思います。

作成するURLスキームはsampleとして進めていきます
sampleをURLスキームとした例は以下のようになります
  sample://hogehoge/fuga/index.html

独自URLスキームのハンドリング


func webViewを独自URLスキームを判定する為に以下のような内容で編集します
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    let url = request.URL!.absoluteString
    if url.hasPrefix("sample://") {
        // 何かしらの処理
        return false
    }
    return true
}
request.URL!.absoluteStringでリクエストURLのフルパスを取得しています
次の行のif url.hasPrefix("sample://")で独自URLスキームかどうかの判定をしています

画面遷移(トップメニュー画面→サブ画面)


トップメニュー画面からサブ画面の画面遷移を実装してみたいと思います。
別のHTMLをロードしてほしいリクエストURLをsample://html/XXXXとします
XXXにはロードしたいhtml名を設定します。
例) menu.htmlからsub.htmlを表示させたい時
sample://html/sub
URLはサンプル用です
html名を与えたらhtmlをロードしてくれるメソッドを作成します
private func locationChanged(res :String) {
    let url = NSBundle.mainBundle().pathForResource(res, ofType: "html");
    let reqURL = NSURL(string: url!)
    let req = NSURLRequest(URL: reqURL!)
    webView.loadRequest(req)
}
↑では引数のresの名前+拡張子がhtmlのリソースパスを取得し、
リソースパスをリクエストURLに変換しUIWebViewにロードさせています
作成したメソッドを使ってfunc webViewを以下のように修正します
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    let url = request.URL!.absoluteString
    if url.hasPrefix("sample://") {
        if url == "sample://html/sub { ・・
          locationChanged("sub")
        }
        return false
    }
    return true
}
リクエストURLがsample://html/subの場合locationChanged
引数"sub"を渡して呼び出しています
  • menu.html
<!doctype html>
<html ng-app="myApp">
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
    </head>
    <body>
        <div>
            <label>Name:</label>
            <input type="text" ng-model="yourName" placeholder="Enter a name here">
            <hr>
            <h1>Hello {{yourName}}!</h1>
        </div>
        <div>
            <form ng-controller="myController">
                <lable>Link:</label>
                <button ng-click="onClick()">send</button>
            </form>
        </div>
    </body>
    <script>
        angular.module('myApp', [])
            .controller('myController', ['$scope', function($scope) {
                // setting click listener
                $scope.onClick = function() {
                    location.href = "sample://html/sub";・・
                };
            }]);
    </script>
</html>
前回作成したindex.htmlでのボタン押したリンク先をサブ画面に変更しています
  • sub.html
<!doctype html>
<html>
    <head>
        <title>Sub Screen</title>
    </head>
    <body>
        <h2>Sub Screen</h2>
    </body>
</html>
サブ画面はいたって単純でSub Screenと表示するだけです
↓画面遷移の様子
optimaize

画面遷移(トップメニュー画面→メイン画面)


トップメニュー画面からメイン画面への遷移ですが、
こちらも特定のリクエストURLの場合にハンドリングするのは変わらず、
ハンドリングしたら別UIViewControllerへ遷移させます
別UIViewControllerへ遷移する為のメソッドを作成します
// Screen transition MainViewController.
private func startMainView() {
    let mainViewController = self.storyboard!
        .instantiateViewControllerWithIdentifier("mainview")
    self.presentViewController(mainViewController, animated: false, completion: nil)
}
↑ではストーリーボード上の遷移先のStoryboard IDmainviewを取得し
presentViewControllerで画面遷移させています
Storyboard IDのつけ方
storyboardid

今度はsample://html/subのリクエストURLが来たら
startMainViewを呼ぶようにfunc webViewを変更します
// handling event
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    let url = request.URL!.absoluteString
    if url.hasPrefix("sample://") {
        if url == "sample://html/sub" {
            locationChanged("sub")
        } else if url == "sample://html/main" {・・
            startMainView()
        }
        return false
    }
    return true
}
また、menu.htmlもメイン画面へのリンクボタンを追加します
<!doctype html>
<html ng-app="myApp">
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
    </head>
    <body>
        <div>
            <label>Name:</label>
            <input type="text" ng-model="yourName" placeholder="Enter a name here">
            <hr>
            <h1>Hello {{yourName}}!</h1>
        </div>
        <div>
            <form ng-controller="myController">
                <lable>Link: Sub</label>
                <button ng-click="onClickSub()">send</button>
                <lable>Link: MainView</label>
                <button ng-click="onClickMain()">go</button>
            </form>
        </div>
    </body>
    <script>
        angular.module('myApp', [])
            .controller('myController', ['$scope', function($scope) {
                // setting click listener
                $scope.onClickSub = function() {
                    location.href = "sample://html/sub";
                };

                // setting click listener
                $scope.onClickMain = function() {・・
                    location.href = "sample://html/main";
                };
            }]);
    </script>
</html>
↓実行結果
optimaize

0 件のコメント:

コメントを投稿