artemyarulin / JSCoreBom

JavaScriptCore is missing some things you get used to - setTimeout, XMLHttpRequest, etc. This projects extends JSContext with native implementation of BOM using Objective-C
MIT License
59 stars 7 forks source link

Use library to execute async function #1

Closed acegreen closed 9 years ago

acegreen commented 9 years ago

Hello,

I was wondering if I can use this library to pause my function while the async function within it is executed

On iOS I do:

        let script = "getImageURL(widget)"

        let jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext

        print(jsContext.evaluateScript(script))

On my server I have:

        function getImageURL(object) {
            var imageURL;
            object.executeActionById("takeScreenshot");
            object.onScreenshotReady(function(imageName) {
                return imageName
            });
        };

The call is being made as I see the alert with the name but what I'm not getting my return value as it seems to execute before it can get it.

I also tried

let script = "getImageURL(widget, function(url) { return imageName })"

and a function like this:

        function getImageURL(object, callback) {
            var imageURL;
            object.executeActionById("takeScreenshot");
            object.onScreenshotReady(function(imageName) {
                callback(imageName)
            });
        };

again, the call is made and I can see the alert but I don't get anything on my iOS side. I want a variable = imageName on iOS side

artemyarulin commented 9 years ago

Hi, well I don't think this library can do anything about it. But basically you just want to execute async function in JS and get a callback on native side? This is totally possible using JavaScriptCore API.

First you should get a reference to your function: JSValue *f = context[@"getImageURL"]; JSValue has a method called: callWithArguments.

So it will look at the end smth like that:

[f callWithArguments:@["FirstParam",^(NSString* callbackValue) {
  NSLog(@"Got a value: %@",callbackValue)
}]
acegreen commented 9 years ago

Thanks for the response!

So I tried the following in Swift but I'm getting an error:

        let script: JSValue = jsContext.objectForKeyedSubscript("getImageURL")
        script.callWithArguments(["widget", callbackvalue {

            print("Got callback value")
        }])

        print(script)

I'm getting unresolved identifier callbackvalue. I'm not sure how to translate ^(NSString* callbackValue) into Swift as I'm don't have an Objective-C background.

artemyarulin commented 9 years ago

I don't have any Swift expirience, sorry :) Have a look maybe here: http://stackoverflow.com/questions/24297430/swift-syntax-for-block-with-completionhandler-in-delegate-method

acegreen commented 9 years ago

Ok I tried to do the following but its a little confusing because callWithArguments, Still getting an error that it expects "," separator

        script.callWithArguments(["widget", callbackHandler: { (callbackvalue: NSString) -> NSString in
        }])
acegreen commented 9 years ago

@artemyarulin just to point out, I want imageName on iOS after the callback is executed thats really the whole point of adding a callback. we don't get imageName unless object.onScreenshotReady is executed. With my previous attempts, the getImageURL would return nothing because it seems to execute before that async object.onScreenshotReady is done (in it I had return imageName