7

In my app I need to send an array from Objective C to javascript. I read on the web that I can use this instruction: stringByEvaluatingJavaScriptFromString, also i made so:

Objective C snippet

NSMutableArray *names = [[NSMutableArray alloc]init];
NSMutableArray *srcs = [[NSMutableArray alloc]init];
for (int i = 0; i < [site count]; i++) {
    NSDictionary *dictData = [site objectAtIndex:i];
    [names addObject:[dictData objectForKey:@"name"]];
    [srcs addObject:[dictData objectForKey:@"src"]];
}
// UPDATE
NSData *jsonArray = [self arrayToJson:nameSrc];
NSString *jsonString = [[NSString alloc]initWithData:jsonArray encoding:NSUTF8StringEncoding];
NSString *econdedString = [self base64String:jsonString];
NSString *jsCall = [NSString stringWithFormat:@"dataFromObjC(\"%@\")", econdedString];
[self.webView stringByEvaluatingJavaScriptFromString:jsCall];

So in javascript I made a function that has this name dataFromObjC(names, srcs), but it doesn't shows me the alert I made. I will post here the complete code of my html so you can help me to solve this problem.

HTML code

<!DOCTYPE html>
<html lang="it">
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>  
        <title>Lista coupon</title>
        <script src="../js/jquery-1.9.1.min.js" type="text/javascript"></script>
        <script src="../js/memoria.js"          type="text/javascript"></script>
        <script type="text/javascript" src="../js/base64.js"></script>
        <script type="text/javascript">
            function dataFromObjC(encodedArray) {
                var jsonString = Base64.decode(encodedArray);
                var arrayFromiOS = JSON.parse(jsonString);
                alert(jsonString);
            }
        </script>
        <style type="text/css">
            body {
                background-color: #000000;
                width: 100%;
                height: 100%;
                padding: 0;
                margin: 0;
            }
            ul {
                list-style-type: none;
                padding: 5px;
            }
            li {
                color: #FFFFFF;
                font-family: sans-serif;
                padding-bottom: 5px;
            }
            p {
                color: #FFFFFF;
                font-family: sans-serif;
                padding: 5px;
                text-align: center;
            }
            a {
                text-decoration: none;
                color: #FFFFFF;
            }
        </style>
    </head>
    <body onload="loadJson();">
        <div id="header">
        </div>
        <div id="content">
            <p>Di seguito trovi tutte le promozioni salvate</p>
            <div id="list">
            </div>          
        </div>
        <div id="footer">

        </div>
    </body>
</html>

I hope that you can help me.

Thank you

lucgian84
  • 833
  • 4
  • 11
  • 29
  • You should encode all your data as JSON using `NSJSONSerialization` and decode it once you're in JS land. – Mike Weller Aug 01 '13 at 09:51
  • @MikeWeller: Let's see if I understand well: also in objective C I've to encode the 2 NSArray with `NSJSONSerialization` and then in javascript I've to decode? Can you explain me better maybe can you write your solution as an answer? – lucgian84 Aug 01 '13 at 09:54

1 Answers1

10
  • First, encode your data to a JSON string instead of a plain string, before sending it to JS. You can do this with NSJSONSerialization.

    - (NSData *) arrayToJSON:(NSArray *) inputArray
    {
        NSError *error = nil;
        id result = [NSJSONSerialization dataWithJSONObject:inputArray 
                                                    options:kNilOptions error:&error];
        if (error != nil) return nil;
        return result;    
    }
    
  • Send it to JS with stringByEvaluatingJavaScriptFromString:. Optionally, I would recommend you to encode the string with Base64, to avoid problems with special characters.

    // Convert your array to JSON data
    NSData *jsonArray = [self arrayToJSON: yourArray];
    // Pass the JSON to an UTF8 string
    NSString *jsonString = [[NSString alloc] initWithData:jsonArray                         
                                                  encoding:NSUTF8StringEncoding];
    // Base64 encode the string to avoid problems
    NSString *encodedString = [Base64 encode:jsonString];
    // Evaluate your JavaScript function with the encoded string as input
    NSString *jsCall = [NSString stringWithFormat:@"yourJsFunction(\"%@\")", encodedString];
    [self.webView stringByEvaluatingJavaScriptFromString:jsCall];
    
  • Once in JS, parse the JSON string to an object (optionally, remember to decode it if you encode first).

    function yourJsFunction(encodedArray)
    {
        // Decode and parse the received input
        var jsonString = Base64.decode(encodedArray);
        var arrayFromiOS = JSON.parse(jsonString);
    }
    

UPDATE: About Base64 utilities for iOS and JS, Internet is plenty of examples of functions and libraries, like these ones for iOS and these other ones for JS. You can choose the one you prefer.

Community
  • 1
  • 1
veducm
  • 5,933
  • 2
  • 34
  • 40
  • You think I should encode my `javascriptString` with an external library and pass to the javascript by using this: `[self.webView stringByEvaluatingJavaScriptFromString:javascriptString];` – lucgian84 Aug 01 '13 at 10:34
  • Yes, it would be safer to encode and decode the string with Base64 for example, to avoid problems with some special characters. – veducm Aug 01 '13 at 10:41
  • I have added a complete example so you can actually test it and let me know if it works. Hope it helps! – veducm Aug 01 '13 at 11:12
  • Ok I put your code in my app, but still having problems: What's Base64 xCode mark it as an error? Why you make this `@"yourJsFunction(\"encodedString\")"`? I don't have to make a `NSString *javascriptString = [NSString stringWithFormat:@"@"yourJsFunction(\%@\)", encodedString];`? – lucgian84 Aug 01 '13 at 11:35
  • Base64 is just an example name, you need to include a Base64 encode/decoding tool for iOS, Internet is plenty of examples, like this ones. Just choose the one you prefer. About the encodedString, sorry that was my mistake, I'll update the code now. – veducm Aug 01 '13 at 11:38
  • Internet is plenty of examples of Base64 functions to encode and decode from iOS and JS, like [these](http://stackoverflow.com/questions/4838263/converting-nsstring-to-base64-data-for-xml-serialization/4844018#4844018) [ones](https://github.com/nicklockwood/Base64) for iOS and this [one](https://github.com/dankogai/js-base64) for JS. – veducm Aug 01 '13 at 11:45
  • To encode I found this: http://www.calebmadrigal.com/string-to-base64-string-in-objective-c/ To decode I use your solution, but I can't see the alert I provide in my html code... Why it's not working? (Look at my question I update the code) – lucgian84 Aug 01 '13 at 12:43
  • Can you check if your JS function(dataFromObjC) is triggered at all? Just put an alert as the first instruction inside this function and see if you see it. – veducm Aug 01 '13 at 12:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/34626/discussion-between-paolo-robertetti-and-veducm) – lucgian84 Aug 01 '13 at 12:57