В этой статье я кратко расскажу, как взаимодействовать с (Angular) Javascript в WKWebView и Native Code. В основном это означает использование Javascript для вызова функции в собственном коде вашего приложения iOS (Swift) и наоборот.

Первым делом вы объявляете свой WKWebView:

var webView: WKWebView?
var request: NSURLRequest!
var url: NSURL!
//Then we add the WKWebViewConfiguration
var webConfig: WKWebViewConfiguration {
    get {
        let webCfg = WKWebViewConfiguration()
        let userController = WKUserContentController()
        let nativeCallHandler = NativeCallHandler()
        nativeCallHandler.delegate = self
        userController.addScriptMessageHandler(nativeCallHandler, name: "onNativeCalled")
        webCfg.userContentController = userController;
        return webCfg;
    }
}

По сути, то, что мы сделали выше, заключалось в том, что в первую очередь я объявил WKWebView, а затем WKWebViewConfiguration, который представляет собой набор свойств, с помощью которых можно инициализировать веб-представление. Затем перейдем к нашему viewDidLoad

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
initViews()
}
func initViews() {
        
    // The URL to load
    url = NSURL(string: "http://sosososandso.com")
// Initialize our NSURLRequest
    request = NSURLRequest(URL: url!)
// Set the frame of our WKWebView and add a configuration
    webView = WKWebView(frame: self.view.frame, configuration: webConfig)
    webView!.translatesAutoresizingMaskIntoConstraints = false
// Then we told our webview to load the request
    webView!.loadRequest(request)
// Then we hooked it up to the webview navigation delegate. This is // not needed, just to debug the webview and know when the WKWebview // MessageHandler is
webView!.navigationDelegate = self
    self.view.addSubview(webView!)
}

Итак, чтобы вызвать WKScriptMessageHandler, нам нужно создать класс NativeCallHandler и позволить ему создать подклассы NSObject и WKScriptMessageHandler. Затем мы переопределяем следующий метод

func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)

Глядя на все это должно быть так:

class NativeCallHandler: NSObject, WKScriptMessageHandler {
    func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
if let messageBody: NSDictionary = message.body as? NSDictionary {
if let innerBody: NSDictionary = messageBody["body"] as? NSDictionary {
                print(innerBody)
            }
        }
    }
}

Выше мы просто сослались на ссылку на объект Dictionary и получили доступ к данным в нем.

По сути, это все, что вам нужно сделать, чтобы вызвать функцию, объявленную в вашем родном приложении iOS.

Что, если мы захотим вызвать функцию в нашем (Angular) коде Javascript?

На самом деле это очень просто:

webView?.evaluateJavaScript("callJSFunc('\(anyParameter requested by the JS function)')", completionHandler: nil)

NB: Пожалуйста, обратите внимание на функцию, названную выше. Перед «\» и после него стоит «‘ ». Если его не добавить, возникнет ошибка NSLocalizedDescription = Исключение JavaScript. Потому что вы неправильно ссылаетесь на функцию JS.

Итак, позвольте мне показать вам фрагмент кода Angular, вызывающего код собственного приложения.

$scope.$on('application', function(e, args){
    var isMobile = {
        Android: function() {
            return navigator.userAgent.match(/Android/i);
        },
        BlackBerry: function() {
            return navigator.userAgent.match(/BlackBerry/i);
        },
        iOS: function() {
            return navigator.userAgent.match(/iPhone|iPad|iPod/i);
        },
        Opera: function() {
            return navigator.userAgent.match(/Opera Mini/i);
        },
        Windows: function() {
            return navigator.userAgent.match(/IEMobile/i);
        },
        any: function() {
            return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
        }
    };
    if(isMobile.Android()){
        window.verifiInterface.verifiID(parameterToPass); 
//This is calling an android function
    }
    if(isMobile.iOS()){
        var postObject = {
            body: {
                params: parameterToPass
            }
        };
        window.webkit.messageHandlers.onNativeCalled.postMessage(postObject);
//This is passing message through WKWebView MessageHandler to the Native App
    }
});

Но тогда, что, если мы хотим объявить нашу функцию для получения сообщения от приложения iOS.

window.callJSFunc = function(theParameter){
    $scope.$apply(function(){
        // Do whatever you want to do with data passed
    });
};

И все. Возможно, в следующем посте я расскажу вам, как реализовать это для Android.