UIWebView内のローカルHTMLでjavascriptを動かす
iOSアプリでローカルHTML(アプリ内に置いたHTML)を表示させるにはUIWebViewを使用します。cssやjavascriptも実行することができます。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ページに分けるだけのことです。
以下はイメージ図です。
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データを受け取っています。表示方法は省略しています。