やりたいこと

ある案件でアプリ内部組み込みブラウザのトラフィックを監視する必要が生まれた。
だから、当初はURLProtocolを使ってハンドリングしようとも考えたが、
URLProtocolUIWebViewでしか使えないので色々悩んだ結果
PrivateAPIに手を出してみたと言うお話。

実装

iOS11以上であれば全く難しくはない
iOS11未満であってもできなくはないがPrivateClassをNSClassFromString(:)
で持ってきて...
って話になるので割愛

WKURLSchemeHandlerなるものがあるのでそれで実装する。

let config = WKWebViewConfiguration()
config.setURLSchemeHandler(WebViewProtocol(), forURLScheme: "dummy")//_urlSchemeHandlersはlazyなのでdummyで初期化してあげる必要がある。

let _handlers = config.value(forKey: "_urlSchemeHandlers") as! NSMutableDictionary

_handlers.setObject(WebViewProtocol(), forKey: "https" as NSString)
_handlers.setObject(WebViewProtocol(), forKey: "http" as NSString)

webview = WKWebView(frame: self.view.frame, configuration: config)

ポイントは
WKWebViewConfiguration::setURLSchemeHandler
で"http","https"を登録すると落ちる(落とされる)ので
value(forKey:)"_urlSchemeHandlers"をそのままいじってしまうこと

(NSMutableDictionaryはクラスなので参照渡し)

んであとはProtocolの中身を書いてしまえばよい

import WebKit
import Alamofire

class WebViewProtocol:NSObject, WKURLSchemeHandler {
    func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
        print(urlSchemeTask.request)
        Alamofire.request(urlSchemeTask.request).response(queue: .main){res in
            if let error = res.error{
                urlSchemeTask.didFailWithError(error)
            }
            urlSchemeTask.didReceive(res.response!)
            urlSchemeTask.didReceive(res.data!)
            urlSchemeTask.didFinish()
        }
    }
    func webView(_ webView: WKWebView, stop urlSchemeTask: WKURLSchemeTask) {

    }
}

まとめ

多分今後PrivateAPIについてもさもさ書くと思います。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.