0

I'm trying to get data from my web service (which is written in python) and send it to javascript of the .html file which i'm showing within a webView in my iOS project.

So far i can get data from my web service successfully. I've checked validity of the returning JSON (from here: link) It's basically like this:

 [
     ["", "2012", "2013", "2014(YTD)"],
     ["Ferrari", 1460089088.3900001, 1637243070.99, 283566771.55000001],
     ["Alfa Romeo", 1199141138.1900001, 1224624821.1500001, 192307335.49000001],
     ["Aston Martin", 938498003.79999995, 925839633.51999998, 153081173.83000001],
     ["Renault", 533421162.11000001, 760272188.90999997, 148547868.22],
     ["Mercedez Benz", 808073299.64999998, 792529238.65999997, 129659242.28],
     ["BMW", 688060328.04999995, 707948227.46000004, 128892192.08],
     ["Bugatti", 583436131.62, 688728665.89999998, 126492338.84999999],
     ["Volvo", 677868130.54999995, 684122911.88, 116283383.16],
     ["Lamborghini", 629542913.95000005, 590023385.53999996, 109498672.36],
     ["Maserati", 694555075.96000004, 631471868.38, 99944513.939999998]
 ]

I want to get these data from my web service and display it on a table which is in an html file. I use a handsontable jQuery plugin to display data in a table.

Below you can see my code in objective-c side. I take asnwer of this stackoverflow article as reference: Send NSArray to javascript

- (void)fetchTableData{
    NSURL *url = [NSURL URLWithString:@"http://xx.xx.xx.xx:yy/myWebService"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    NSError *error;

    //jsonArray=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];


    // Pass the JSON to an UTF8 string
    NSString *jsonString = [[NSString alloc] initWithData:data 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:@"myData=('%@');", jsonString];

    // _grid is my webView
    [_grid stringByEvaluatingJavaScriptFromString:jsCall];
}

And here is my .html file:

<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">


    <link rel="stylesheet" type="text/css" href="/css/result-light.css">


    <script src="http://warpech.github.io/jquery-handsontable/lib/jquery.min.js"></script>
    <script src="http://warpech.github.io/jquery-handsontable/dist/jquery.handsontable.full.js"></script>
    <link rel="stylesheet" media="screen" href="http://warpech.github.io/jquery-handsontable/dist/jquery.handsontable.full.css">
    <link rel="stylesheet" media="screen" href="http://warpech.github.io/jquery-handsontable/demo/css/samples.css?20140401">

    <style type="text/css">
        body {
            background: white;
            margin: 20px;
        }
        h2 {
            margin: 20px 0;
        }
    </style>



    <script type='text/javascript'>
        //<![CDATA[

        $(document).ready(function () {

            var myData = ();

            //                                              var myData = ( [
            //                                                              ["", "2012", "2013", "2014(YTD)"],
            //                                                              ["Ferrari", 1460089088.3900001, 1637243070.99, 283566771.55000001],
            //                                                              ["Alfa Romeo", 1199141138.1900001, 1224624821.1500001, 192307335.49000001],
            //                                                              ["Aston Martin", 938498003.79999995, 925839633.51999998, 153081173.83000001],
            //                                                              ["Renault", 533421162.11000001, 760272188.90999997, 148547868.22],
            //                                                              ["Mercedez Benz", 808073299.64999998, 792529238.65999997, 129659242.28],
            //                                                              ["BMW", 688060328.04999995, 707948227.46000004, 128892192.08],
            //                                                              ["Bugatti", 583436131.62, 688728665.89999998, 126492338.84999999],
            //                                                              ["Volvo", 677868130.54999995, 684122911.88, 116283383.16],
            //                                                              ["Lamborghini", 629542913.95000005, 590023385.53999996, 109498672.36],
            //                                                              ["Maserati", 694555075.96000004, 631471868.38, 99944513.939999998]
            //                                                              ]);

            $('#myTable').handsontable({
                data: myData,
                minSpareRows: 1,
                //colHeaders: true,
                contextMenu: true,
                readOnly: true,
                fixedColumnsLeft: 1
            });


            function bindDumpButton() {
                $('body').on('click', 'button[name=dump]', function () {
                    var dump = $(this).data('dump');
                    var $container = $(dump);
                    console.log('data of ' + dump, $container.handsontable('getData'));
                });
            }
        });
         //]]>
    </script>


</head>

<body>


    <div id="myTable" class="handsontable" style="width: 400px; margin-left:auto; margin-right:auto; background-color:silver"></div>

</body>


</html>

In my viewDidLoad method and displayGrid method which i wrote to connect my webView with .html file everything is appropriate.

But when i run the code, i see my webView blank becase there is no data trasnmission from webservice to javascript. How can i achieve this?


After simon Mclaughlin'a advice, I changed code like: this:

JavaScript:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8">


            <link rel="stylesheet" type="text/css" href="/css/result-light.css">


                <script src="http://warpech.github.io/jquery-handsontable/lib/jquery.min.js"></script>
                <script src="http://warpech.github.io/jquery-handsontable/dist/jquery.handsontable.full.js"></script>
                <link rel="stylesheet" media="screen" href="http://warpech.github.io/jquery-handsontable/dist/jquery.handsontable.full.css">
                    <link rel="stylesheet" media="screen" href="http://warpech.github.io/jquery-handsontable/demo/css/samples.css?20140401">

                        <style type="text/css">
                            body {background: white; margin: 20px;}
                            h2 {margin: 20px 0;}

                            </style>



                     <script type='text/javascript'>

                            function dataSender(arr){
                                $('#myTable').handsontable({
                                                           data: arr,
                                                           minSpareRows: 1,
                                                           contextMenu: true,
                                                           readOnly: true,
                                                           fixedColumnsLeft: 1
                                                           });
                            }

//                            $(document).ready(function () {

//                                              var myData = myDataCollection;
//                                              $('#myTable').handsontable({
//                                                                         data: myData,
//                                                                         minSpareRows: 1,
//                                                                         //colHeaders: true,
//                                                                         contextMenu: true,
//                                                                         readOnly: true,
//                                                                         fixedColumnsLeft: 1
//                                                                         });
//                                              
//                                              });


                    </script>
            </head>
    <body>


        <div id="myTable" class="handsontable" style="width: 400px; margin-left:auto; margin-right:auto; background-color:silver"></div>

    </body>


</html>

Objective-C :

#import "TablesScreenViewController.h"

@interface TablesScreenViewController (){
    NSMutableArray *tablesbuttonarray;
    //NSMutableArray *jsonArray;
}

@end

@implementation TablesScreenViewController
@synthesize TopLayer=_TopLayer,layerPosition=_layerPosition,tablesleftSlider=_tablesleftSlider,tablesrightSlider=_tablesrightSlider,tcharts=_tcharts,ttables=_ttables,tnews=_tnews,tRSS=_tRSS,tIHimg=_tIHimg,tsocial=_tsocial,tfeedback=_tfeedback,tabout=_tabout,tlogout=_tlogout,tablesrightbubble=_tablesrightbubble,tablesrightchartstitle=_tablesrightchartstitle,tablesrightindex=_tablesrightindex,tablesrightline=_tablesrightline,tablesrightnewstitle=_tablesrightnewstitle,tablesrightoverview=_tablesrightoverview,tablesrightRSS=_tablesrightRSS,tablesrightSliderimage=_tablesrightSliderimage,tablesrightSocial=_tablesrightSocial,tablesrightstandart=_tablesrightstandart,tablesrighttablestitle=_tablesrighttablestitle,tablesrightwebfeedtitle=_tablesrightwebfeedtitle, grid=_grid;

- (IBAction)panLayer:(UIPanGestureRecognizer *)pan {

    if(pan.state == UIGestureRecognizerStateChanged){
        CGPoint point=[pan translationInView:self.TopLayer];
        CGRect frame=self.TopLayer.frame;
        CGRect rframe=self.TopLayer.frame;

        if (point.x>0) {
            frame.origin.x=self.layerPosition+point.x;
            if(frame.origin.x > 240) frame.origin.x=240;
            self.TopLayer.frame=frame;
        }
        else if(point.x<0){
            rframe.origin.x=self.layerPosition+point.x;
            if(rframe.origin.x < -340) rframe.origin.x=-340;
            self.TopLayer.frame=rframe;


        }
    }

    if(pan.state== UIGestureRecognizerStateEnded){

        if (self.TopLayer.frame.origin.x >0 && self.TopLayer.frame.origin.x <=120) {
            [self animateLayertoPoint:0];
        }
        else if (self.TopLayer.frame.origin.x >120 && self.TopLayer.frame.origin.x <=240){
            [self animateLayertoPoint:240];
        }
        else if (self.TopLayer.frame.origin.x <0 && self.TopLayer.frame.origin.x >= -170){
            [self animateLayertoPoint:0];
        }
        else if (self.TopLayer.frame.origin.x < -170 && self.TopLayer.frame.origin.x >= -340){
            [self animateLayertoPoint:-340];
        }

    }
}

- (void)fetchTableData{


    NSURL *url = [NSURL URLWithString:@"http://xx.xx.xx.xx:yy/myWebService"];
    NSData *data = [NSData dataWithContentsOfURL:url];
    NSError *error; //******

    //jsonArray=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];

    NSLog(@"fetch methoduna girdik");
    // Pass the JSON to an UTF8 string
    NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"jsonString: %@",jsonString);
    [_grid stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"dataSender('%@');", jsonString]];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    return interfaceOrientation == UIInterfaceOrientationLandscapeLeft;
}

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

-(void) animateLayertoPoint:(CGFloat)x{

    [UIView animateWithDuration:1
                          delay:0
                        options:UIViewAnimationOptionCurveEaseOut
                     animations:^{
                         CGRect frame=self.TopLayer.frame;
                         frame.origin.x=x;
                         self.TopLayer.frame=frame;
                     }
                     completion:^(BOOL finished) {
                         self.layerPosition=self.TopLayer.frame.origin.x;
                     }];


}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

-(void)displayGrid{

    NSString *pathOfFile=[[NSBundle mainBundle] pathForResource:@"tables_1" ofType:@"html"];
    NSString *htmlText=[NSString stringWithContentsOfFile:pathOfFile encoding:NSUTF8StringEncoding error:nil];

    NSURL *baseURL = [NSURL fileURLWithPath:pathOfFile];
    [_grid loadHTMLString:htmlText baseURL:baseURL];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    //[self fetchTableData];
    [self displayGrid];
    // Do any additional setup after loading the view.
    tablesbuttonarray = [[NSMutableArray alloc] initWithObjects:_tablesrightline,_tablesrightindex,_tablesrightstandart,_tablesrightoverview,_tablesrightbubble,_tablesrightRSS,_tablesrightSocial,nil];

    [_tablesrightstandart setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    _tablesrightstandart.backgroundColor=[UIColor colorWithRed:0/255.0 green:136/255.0 blue:204/255.0 alpha:1];
    [_tablesrightline setTitleColor:[UIColor colorWithRed:0/255.0 green:136.0/255.0 blue:204.0/255.0 alpha:1] forState:UIControlStateNormal];
    [_tablesrightindex setTitleColor:[UIColor colorWithRed:0/255.0 green:136.0/255.0 blue:204.0/255.0 alpha:1] forState:UIControlStateNormal];
    _ttables.backgroundColor=[UIColor colorWithRed:251/255 green:251/255  blue:251/255  alpha:0.1];
    self.layerPosition=self.TopLayer.frame.origin.x;
    _grid.delegate=self;
    _grid=[[UIWebView alloc]init];
}

-(void) webViewDidFinishLoad:(UIWebView *)webView{
    _grid.delegate=self;
   _grid=[[UIWebView alloc]init];
   [self fetchTableData];
}

//-(void)webViewDidFinishLoad:(UIWebView *)webView {
//    [self fetchTableData];
//}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
-(IBAction)tablesleftSliderButton:(id)sender{
    [UIButton animateWithDuration:1 animations:^{
        CGRect tframe=self.TopLayer.frame;
        if(tframe.origin.x <=0) tframe.origin.x=240;
        else tframe.origin.x=0;
        self.TopLayer.frame=tframe;
    }];
}
-(IBAction)tablesrightSliderButton:(id)sender{
    [UIButton animateWithDuration:1 animations:^{
        CGRect tframe=self.TopLayer.frame;
        if(tframe.origin.x >= -1) tframe.origin.x=-340;
        else tframe.origin.x=0;
        self.TopLayer.frame=tframe;
    }];
}

-(IBAction)tlogoutButton:(id)sender{
    UIAlertView *alert = [[UIAlertView alloc]

                          initWithTitle:@"Are you sure?"
                          message:@""
                          delegate:self
                          cancelButtonTitle:@"Cancel"
                          otherButtonTitles:@"OK", nil];

    [alert show];

}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex == 1) {
        UIStoryboard *main= [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
        UIViewController *vc=[main instantiateViewControllerWithIdentifier:@"LoginViewController"];
        [self presentViewController:vc animated:YES completion:nil];
    }

}


@end
Community
  • 1
  • 1
t1w
  • 1,408
  • 5
  • 25
  • 55

1 Answers1

1

I would bet its that you are passing in the data before the webview is loaded.

Try passing in the data after this callback is fired:

- (void)webViewDidFinishLoad:(UIWebView *)webView 
{
    [self fetchTableData];
}

If you pass the data in before hand the DOM / JS hasn't been parsed and thus can't handle your request to evaluate the JS string.

EDIT

Just noticed your JS code in the html is using the document.ready function. You can't ask the UIWebview to evaluate the JS until it is loaded. You will need to change this around so that your call to pass in the data, calls a function that will trigger your JS code, rather than trying to pass the data in before its started.

Also you could simple use a JS ajax call to get the data as well.

Simon McLoughlin
  • 8,293
  • 5
  • 32
  • 56
  • i'm sorry i didn't understand what you meant by **"You will need to change this around so that your call to pass in the data, calls a function that will trigger your JS code, rather than trying to pass the data in before its started."** Shall i pass my data to another JS function than call it within $(document).ready(function () ? – t1w Apr 22 '14 at 14:53
  • 1
    @TimurAykutYILDIRIM no, forget `document.ready`. You will never be able to get the data in, in time when that is called. Create a new function that takes in your data and calls all your JS code. Then call that function from Objective-c – Simon McLoughlin Apr 22 '14 at 14:55
  • how do i call that function from objective-c? Am i suppose to call it like **NSString *jsCall = [NSString stringWithFormat:@"myData=('%@');", jsonString];** in my fetchTableData function? – t1w Apr 22 '14 at 15:06
  • 1
    @TimurAykutYILDIRIM you don't seem to understand what your code is doing. `[_grid stringByEvaluatingJavaScriptFromString:jsCall];` passes javascript into the webview. e.g. `[_grid stringByEvaluatingJavaScriptFromString: [NSString stringWithFormat:@"myfunctionName(%@)", myWebServiceData] ];`. **myfunctionName** being the name of your new JS function and **myWebServiceData** being the objective c data your passing into it – Simon McLoughlin Apr 22 '14 at 15:37
  • 1
    @TimurAykutYILDIRIM any luck with this? if so don't forget to mark top answer / upvote. If not edit your question with more details and let me know it didn't work. You shouldn't leave questions open as others facing the same issue won't know what solved it – Simon McLoughlin Apr 23 '14 at 08:36
  • Sorry to respond late, I had an exam. I changed code but it shows me nothing. I can get data from webservice into jsonString variable. I'm sure i'm making a silly mistake but i just can't find it. – t1w Apr 24 '14 at 13:48
  • 1
    @TimurAykutYILDIRIM well then edit your question to show me the code your using now, I asked you to edit your question in the previous comment if it didn't work – Simon McLoughlin Apr 24 '14 at 13:53
  • 1
    @TimurAykutYILDIRIM when is `fetchTableData` called? you haven't used the first part of my answer suggesting to use the `webViewDidFinishLoad` callback to pass in the data – Simon McLoughlin Apr 24 '14 at 14:01
  • i wrote webViewDidFinishload right under the viewDidLoad method like this: **-(void) webViewDidFinishLoad:(UIWebView *)webView{ [self fetchTableData]; }** – t1w Apr 24 '14 at 14:28
  • @TimurAykutYILDIRIM please delete the edit you made to your question and instead add the full viewController.m and the full HTML, i need to see how / where the JS is created and I need to see how / where the webview is created, the delegate is set, and see the flow of the logic – Simon McLoughlin Apr 24 '14 at 14:33
  • 1
    @TimurAykutYILDIRIM html looks fine. In the objective-c I see nowhere where you have called `alloc` or `init` on `_grid`, I see nowhere where you have added `_grid` to the viewController `view` and you didn't set the viewController as the `_grid.delegate`, meaning it won't call that `webViewDidFinsihLoading`callback – Simon McLoughlin Apr 24 '14 at 14:52
  • @TimurAykutYILDIRIM in your `viewDidLoad` you are calling `displayGrid` before you have called `alloc] init]` on the webview. Of course it won't work, your asking the webview to do something before it exists. You also calling `alloc] init]` on it again in the `webViewDidFinishLoad`, meaning its going to load, then going to be removed and loaded again. And YET AGAIN you have not added it to viewController view, and haven't given it a frame either – Simon McLoughlin Apr 25 '14 at 10:07
  • @TimurAykutYILDIRIM So to recap, the object is `nil` when you ask it to load the html file, you haven't added the webview to the screen so you will never see anything, you haven't given it a size so if it was added to the screen, you still wouldn't see anything. Placing `alloc] init]` inside the `webViewDidFinishLoad` is basically undoing everything your trying to do. Dude this is beyond basic basic objective-c. Make sure your webview is on the screen first, load `www.google.ie`, when you see that, then try do what ur doing – Simon McLoughlin Apr 25 '14 at 10:08