UIWebView内のローカルHTMLでjavascriptを動かす

iOSアプリでローカルHTML(アプリ内に置いたHTML)を表示させるにはUIWebViewを使用します。cssjavascriptも実行することができます。javascriptを実行させるにはiOSを経由させなければなりません。動かし方は以下の通りです。

object-c
// jQueryを実行する
NSString *jqpath = [[NSBundle mainBundle]pathForResource:@"jquery-1.11.1.min" ofType:@"js"];
NSString *jqCode = [NSString stringWithContentsOfFile:jqpath encoding:NSUTF8StringEncoding error:nil];
[webView stringByEvaluatingJavaScriptFromString:jqCode];


ではもう少し具体的な例を見てみます。ローカル内でGET通信した際、GETデータを取得するためにjavascriptを使用します。

HTML
<a href="detail.html?id=1">一番の詳細表示</a>

このHTMLをクリックして以下のプログラムを動かします。

object-c
// IDを取得するためのJavascript・getid.jsを読み込みます
jspath = [[NSBundle mainBundle] pathForResource:@"getid" ofType:@"js"];
jsCode = [NSString stringWithContentsOfFile:jspath encoding:NSUTF8StringEncoding error:nil];
NSString *id = [self.webView stringByEvaluatingJavaScriptFromString:jsCode];
NSLog(@"id = %@", id);
javascript・getid.js
$(document).ready(function(){

        var url   = location.href;
        parameters    = url.split("?");
        params   = parameters[1].split("&");
  
        var paramsArray = [];
        for ( i = 0; i < params.length; i++ ) {
            param = params[i].split("=");
            paramsArray.push(param[0]);
            paramsArray[param[0]] = param[1];
        }
        var categoryKey = paramsArray["id"];
                  
        return categoryKey;
});

あれ?値が帰ってこないぞ。なぜだ…。jQueryが動いていないのだろうか?調べてみるとjQueryはきちんと動いています。変数categoryKeyにきちんと"1"が入っていました。returnだけされない。なぜ?jQueryはあまり詳しくありません。そこでjQueryをやめてみたところ、値を返しました。

javascript・getid.js改
function f(){

        var url   = location.href;
        parameters    = url.split("?");
        params   = parameters[1].split("&");
  
        var paramsArray = [];
        for ( i = 0; i < params.length; i++ ) {
            param = params[i].split("=");
            paramsArray.push(param[0]);
            paramsArray[param[0]] = param[1];
        }
        var categoryKey = paramsArray["id"];
         
        return categoryKey;
}
f();

webViewDidFinishLoadメソッドの際にjavascriptを実行させればjQueryでreadyを使用する必要はないですよね。jQueryに詳しい方、ご教授ください。
実行結果はNSLogに"id = 1"と表示されます。

wssプロトコルを使用したwebsocketサーバーを構築してみる。

サーバーにnode.jsをインストールしましたので、wssプロトコルを使用したwebsocketサーバーとクライアントを構築してみました。

ただしクライアントは送信側と受信側をそれぞれ別々のページにします。なんのことはない、ただ1ページで行なっていた作業を送信側と受信側の2ページに分けるだけのことです。

以下はイメージ図です。

f:id:kunie_zing:20140824232539p:plain

websocketサーバー with wssプロトコル

var fs = require('fs');
var ws = require('websocket.io');
var https = require('https');
var port = 8080;
var opts = {
  // SSL証明書と秘密鍵を準備する
  key: fs.readFileSync('./server.pem').toString(),
  cert: fs.readFileSync('./server.crt').toString()
};

var ssl_server = https.createServer(opts, function(req, res) {
  res.end();
});

var server = ws.attach(ssl_server);

// クライアントからの接続イベントを処理
server.on('connection', function(socket) {

  // クライアントからのメッセージ受信したとき
  socket.on('message', function(data) {

    console.log('data');

    // 受信したメッセージを全てのクライアントに送信する
    server.clients.forEach(function(client) {
      client.send(data);
    });
  });

  // クライアントが切断したとき
  socket.on('disconnect', function(){
    console.log('connection disconnect');
  });

  // 通信がクローズしたとき
  socket.on('close', function(){
    console.log('connection close');
  });

  // エラーが発生したとき
  socket.on('error', function(err){
    console.log(err);
  });
});


// サーバーを起動し続ける
ssl_server.listen(port, function() {
  console.log('Listening on ' + port);
});

wssプロトコルを使用する際には、SSL証明書とサーバーの秘密鍵が必要です。また受信したメッセージをすべてのクライアントに送信する場合、server.clients.forEach をする必要があります。client.send(data); だけを記述してもメッセージは飛びませんでした。それから、現在サーバーがエラーで停止する現象が出ています。server.clients.forEach でのエラーっぽいです。対処方法ご存知の方は教えてください。

クライアント・送信側

function sendws(){
  jQuery(function($) {
    var socket;
    socket = new WebSocket('wss://www.example.com:8080');
    var socketdata;
    socketdata = new Object();

/*
 *  socketデータ送信準備
*/

    // socketデータ送信
    socket.onopen = function(){ socket.send(JSON.stringify(socketdata)); };
  });
}

socketデータをJSON形式にして送るやり方は省略しています。WebSocketオブジェクトを作成時、wssを指定するのとサーバー側で記述したポート番号を忘れずに。

クライアント・受信側

jQuery(function($) {
  var socket;
  socket = new WebSocket('wss://www.example.com:8080');

  // サーバーに接続したとき
  socket.onopen = function(msg) { 
    $('#status').text('online');
  };

  // サーバーからデータを受信したとき
  socket.onmessage = function(msg) {
    console.log(msg.data);

    var jmsg = $.parseJSON(msg.data);
/*
* socketデータ受信・表示
*/
  };

  // サーバーから切断したとき
  socket.onclose = function(msg) { $('#status').text('offline'); };

});

サーバーへ接続・切断時にstatusにonlineかofflineを表示させるようにしています。websocketでJSONデータを受け取っています。表示方法は省略しています。