iOSガワネイティブでSwiftにでかいデータを受け渡す

2015-02-02
iOSでガワネイティブで、WebViewで動かしてるJavaScriptからSwiftにURLのパラメータに乗せてデータを渡すことができたが、普通URLの長さには制限があるので、もっとでかいデータを渡す場合には違う方法をとる必要がある。

JSからネイティブにでかいデータを受け渡す方法

URLパラメータじゃなく、POSTで送ればある程度のサイズの制限は回避できる。JSからPOSTを送るには例によってAjaxを使う:

// test.js
function foobar(url, stringData) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (200 <= xhr.status && xhr.status < 300) {
// 成功
} else if (xhr.status >= 400) {
// 失敗
}
};
xhr.open('POST', url, false); // 第3引数=asyncかどうか
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send(stringData);
}

foobar('http://native/foobar', 'BigData')
  • 受け渡すデータはa=x&b=y&...という形式でなくても、改行などを含んでいても受け渡すことができる

SwiftでPOSTデータを受け取る

iOSガワネイティブでSwiftから値を受け取ると同様に、NSURLProtocolを継承して拡張したクラスを定義して、所定のURLをフックしてPOSTのデータを受け取る:

// MyURLProtocol.swift
import UIKit

class NativeURLProtocol: NSURLProtocol {
// 以下のメソッドで所定のURLをフック
//override class func canInitWithRequest(request: NSURLRequest) -> Bool
//override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest

override func startLoading() {
// POSTデータを受け取る
let httpBody: NSData? = request.HTTPBody
...
}
}
  • 注意点として、POSTを受け取るURLのスキームはhttphttpsである必要がある。これを自分で独自に定義したスキームを使うとrequest.HTTPBodynilになってしまい、受け取れない。