Асинхронная связь swift и Javascriptcore

Я хочу использовать асинхронную функциональность, предлагаемую WKWebView вне веб-просмотра. Параметр контекста JS не обеспечивает функциональность асинхронности.

В WKWebView я пишу свою логику следующим образом.

func swiftFunc1() {
   webView.evaluateJavaScript("jsFunc1(), completionHandler: nil)
}

В коде javascript я отправляю сообщение Swift

function jsFunc1() {
    window.webkit.messageHandlers.myMsg.postMessage("call swiftFunc2");
}

Затем быстрый код может вызвать соответствующий обратный вызов JS как часть обработки сообщения.

Но это зависит от того, является ли веб-просмотр передним планом. Если я хочу использовать логику JS независимо от веб-просмотра, JContext — это вариант. Я пытался следовать

func swiftFunc1() {
    myCtxt = JSContext()
    exportedToJS = exportToJS() //confirms to JSExport and uses @objc
    myCtxt.setObject(exportedToJS.self, forKeyedSubscript: "swiftIface")
    myFunc = myCtxt.objectForKeyedSubscript("jsFunc1")
    myFunc.callWithArguments(nil)
}

Теперь в коде javascript я не могу отправить сообщение в swift. Если я попытаюсь вызвать быструю функцию следующим образом, код застрянет навсегда.

function jsFunc1() {
   swiftIface.swiftFunc2() // This creates a deadklock
 }

Как я могу добиться любого из следующих действий без «возврата» из вызываемой функции Javascript jsFunc1()?

  1. Либо опубликуйте сообщение для быстрого, чтобы он мог принять соответствующие меры

  2. Или вызовите быструю функцию, чтобы было выполнено соответствующее действие


person Amruta    schedule 09.07.2016    source источник


Ответы (1)


Я правильно вас понимаю, если вы не хотите, чтобы ваш javascript завершался после выполнения?

Если я вас неправильно понял, возможно, следующее поможет (я не дома на Mac, чтобы проверить, но, возможно, это сработает, если вы измените свой код следующим образом).

Вариант 1. Блокировка

swiftFunc1 может выглядеть так:

func swiftFunc1() {
    myCtxt = JSContext()
    myCtxt.setObject(unsafeBitCast(swiftFunc2, AnyObject.self), forKeyedSubscript: "swiftFunc2")
    exportedToJS = exportToJS() //confirms to JSExport and uses @objc
    myCtxt.evaluateScript("swiftFunc2()")
}

Ваш swiftFunc2 будет выглядеть так:

let swiftFunc2: @convention(block) Void -> Void = { 
  // do something here
}

Ваш JS-код будет выглядеть так:

function jsFunc1() {
   swiftFunc2();
 }

Вариант 2: JSExport У вас есть экспортированный класс, доступный для всех javascript:

import Foundation
import JavaScriptCore
@objc class JavascriptHandler: NSObject, JavascriptHandlerExport {
  let context: JSContext = JSContext()

  init () {
    context.setObject(self, forKeyedSubscript: "MyJSHandler") // set the object name for self accessible in javascript code
  }
  func swiftFunc1() {
    context.evaluateScript("MyJSHandler.swiftFunc2();")
  }
  func swiftFunc2 () {
    // do something here
  }
}

Ваш протокол для экспортируемого класса. Здесь вы должны объявить все свойства и методы, которые хотите использовать с Javascript.

import Foundation
import JavaScriptCore
@objc protocol JavascriptHandlerExport: JSExport {
  func swiftFunc2 ( ) -> Void
}

При этом у вас должна быть возможность вызывать функцию из javascript и при этом продолжать ее работу. Теперь вы можете получить доступ к функциям класса JavascriptHandler из Javascript, как в этом примере:

MyJSHandler.swiftFunc2();

Если вы хотите отделить класс, в котором находится ваш WebView, от класса, в котором находится ваша логика JS, это также не должно быть проблемой. Вы также должны иметь возможность комбинировать синтаксис блока с методом JSExport.

Дайте мне знать, если он не работает/ведет себя не так, как хотелось бы.

person commonist    schedule 12.07.2016
comment
Спасибо за ответ. Но значит ли это, что я должен использовать только блоки/замыкания, чтобы обойти это? JSExport не может обрабатывать такую ​​последовательность вызовов, не так ли? - person Amruta; 13.07.2016
comment
Это должно быть возможно и с JSExport. Может быть, если у меня будет время завтра, я могу попытаться привести пример. - person commonist; 14.07.2016
comment
С нетерпением жду этого! - person Amruta; 14.07.2016
comment
Не могли бы вы найти это возможным? - person Amruta; 16.07.2016
comment
Ранее я пробовал такое расположение и обнаружил, что XCode просто зависает, когда есть такой цикл. См. stackoverflow.com/questions/37908059/ - person Amruta; 17.07.2016
comment
Извините, возможно, в будущем я смогу провести тесты на этом, но, к сожалению, не сейчас... - person commonist; 24.07.2016