Wednesday, April 18, 2012

Cordova/PhoneGap iOS Plugin Return Result

Someone raised an excellent question on how to get the return result from a Cordova/PhoneGap iOS plugin. The articles from phonegap.com and from adobe.com do give an answer but you have to look very carefully and there is a much easier way which I will document here for the iOS and in another post for the Android.

Basically, a Cordova/PhoneGap plugin returns a result asynchronously by sending some Javascript code to be executed in the app's browser. Here is an example from the DatePicker plugin, with small adaptions to make it easier to read (extra spacing, using single quote in Javascript string):

- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
{
    NSString* jsCallback = [NSString stringWithFormat:
        @"window.plugins.datePicker._dateSelected('%i');",
        (int)[self.datePicker.date timeIntervalSince1970]];
    [super writeJavascript:jsCallback];
}


So this code actually wants to execute a piece of code on the Javascript side to report a result that a date had been selected. Here is the code on the Javascript side that will be called back with the date that has been selected:

    DatePicker.prototype._dateSelected = function(date) {
        var d = new Date(parseFloat(date)*1000);
        if (this._callback)
            this._callback(d);
    }


Assuming you remember how prototype works you can see that this function will parse the value that is returned and make a callback to the Javascript application code, if it exists.


Update to answer a comment: the _callback member is set according to a parameter from the original function call, for example:
    DatePicker.prototype.show = function(options, cb) {
        // [options code omitted, TBD describe in another post]
        this._callback = cb;
        Cordova.exec("DatePicker.show", options);
    } 

The Cordova/PhoneGap documents describe how to use a CDVPluginResult object to return a plugin result object with data that will be sent to either a success callback or an error callback that was passed into cordova.exec() function but I find the method described here much easier to understand and debug.