简体   繁体   中英

Swift: How to wrap an async method in a synchronous method?

I'm trying to load Javascript synchronously in my WKWebView . From my research it looks like the evaluateJavaScript method is asynchronous and this is causing errors because the page would load before the JS that overrides a lot of behavior (it only works a portion of the time because of the async nature).

I've tried this but it doesn't seem to work :

extension WKWebView {
  func evaluateJavaScriptSynchronously(script: String, completion: () -> Void) {
    let semaphore = dispatch_semaphore_create(1)

    evaluateJavaScript(script) { (result, error) in
      if error == nil {
        if result != nil {
          print("SUCCESS")
          completion()
        }
      } else {
        print("ERROR!!!")
        print(error)
        print(result)
        completion()
      }
      dispatch_semaphore_signal(semaphore)
    }

    let timeout = dispatch_time_t(10000)
    dispatch_semaphore_wait(semaphore, timeout)
  }
}

I know it's not working because the page still sometimes loads as if the JS wasn't there. Is there a similar thing I can do to synchronize the process?

You can define a WKNavigationDelegate to get notified when the page into the WKWebView has been loaded

class Controller: UIViewController, WKNavigationDelegate {

    @IBOutlet var webView: WKWebView!

    override func viewDidLoad() {
        self.view = webView
        webView.navigationDelegate = self
    }

    func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
        print("page loaded")
        // <--- call your method from here
    }
}

You can now call your method from within webView(wevView:didFinishNavigation:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM