LoginSignup
42
47

More than 5 years have passed since last update.

SwiftとJavascriptの通信

Last updated at Posted at 2015-04-18

UIWebViewのJavascriptとSwiftの相互のやり取りについて調べてみた。WKWebViewを使えばスマートに出来そうだけど、ios7で使いたかったので、WKWebViewを使わない方向で実装してみました。

ライブラリ(というほど大層なものではないですが)にしたので参考までにどうぞ。
https://github.com/gomo/JsNoty

PullToRefreshでAjaxを読み込みたい場合などに活躍すると思います。

SwiftからJavascriptへ

これは単純にstringByEvaluatingJavaScriptFromStringでイベントをfireしてあげればいけますね。

let script = String(format: "document.dispatchEvent(new CustomEvent(\"%@\", {detail:%@}))", name, "{foo:\"bar\"}");

データを渡したい時は{detail:%@}というキーに入れるとJS側で取得できます。jQueryを使ってる時はevent. originalEvent.detailになるのでそこを探してください。

JavascriptからSwiftへ

これは適当はprotocolでページをロードし、UIWebViewDelegate::shouldStartLoadWithRequestで捕まえるのが一般的なようです。

Javascript側からは

location.href = 'jsnoty://foobar/';

Swift側では

class ViewController: UIViewController, UIWebViewDelegate, JsNotyDelegate {
    private var jsNoty:JsNoty!;
    override func viewDidLoad() {
        super.viewDidLoad()

        self.jsNoty = JsNoty(webView: self.webView)
        self.jsNoty.delegate = self

        let url = NSURL(string: "http://www.expample.com/path/to/page.html")
        let request = NSURLRequest(URL: url!)
        self.webView.loadRequest(request)
    }

    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        if(request.URL!.scheme == "jsnoty"){
            //ここで何かする
            return false;
        }

        return true
    }

気をつけないといけないのはwindow.onloadの中で呼ばないと、jsnoty://foobar/が出ちゃいます。Chromeではページが読み込まれた後だと、存在しないprotocalの場合ページ遷移をしないようですが、ブラウザの互換を調べてないので、UIWebViewからのアクセス以外はしない方がいいかもしれません。

もう1点、Swift側で受信してから次を呼ばないと認識できないっぽいです。なのでJsNotyではキューイングして、Swift側の処理をまって次を呼ぶようにしました。自分で実装するとここがちょっと面倒かも。

ちなみに、iosからの接続時にUserAgentを書き換える方法も書いておきます。この3つを組み合わせれば、UIWebViewとWebページとの連携は大抵のことが出来ると思います。

UserAgentの書き換えは、最初の送信の前にやらないとダメなようです。なのでAppDelegateでやるようです。

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        //UserAgentを上書き
        let webView:UIWebView = UIWebView()
        let userAgent:String! = webView.stringByEvaluatingJavaScriptFromString("navigator.userAgent")
        let customUserAgent:String = userAgent.stringByAppendingString(" from.ios.UIWebView")

        let dic:NSDictionary = ["UserAgent":customUserAgent]
        NSUserDefaults.standardUserDefaults().registerDefaults(dic as [NSObject : AnyObject])

        return true
    }
42
47
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
47