0

My current issue is I have successfully fetched data from a web service using SBJSON as well as parsed the data into a Class with several variables.

Now, my main view controller is supposed to be accessing those variables within the Class that is pulling data from the web service but every time I access the variables, all are null or 0.

I figure the issue is because when the application has already launched to the main view controller, the class that pulls the data from the Web Server isn't loaded yet.

How do I resolve this?

Here is the code for the main view controller.

- (void)viewDidLoad
{

    _mainParser = [[MonroeParser alloc] init];
    [_mainParser go];

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    UINavigationBar *navBar = [[self navigationController] navigationBar];
    navBar.tintColor = [UIColor redColor];
    UIImageView* img = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Power_One_RedLogo.png"]];
    self.navigationItem.titleView = img;

    UIBarButtonItem *iconButton = [[UIBarButtonItem alloc] initWithTitle:@"View Site" style:UIBarButtonItemStylePlain target:self action:@selector(pushToPowerOneWebsite:)];
    self.navigationItem.leftBarButtonItem = iconButton;


    _DayString.text = @"Thursday";
    _DayInteger.text = @"24";
    _MonthString.text = @"May";
    _SystemStatusIcon.image = [UIImage imageNamed:@"Power_One_RedLogo.png"] ;
    _SystemStatus.text = @"Normal";

    [_StatusButton addSubview:_DayInteger];



    NSLog(@"%@", _mainParser.solarStatus);
    NSLog(@"%@", _mainParser.fields);
    NSLog(@"%@", _mainParser.type);
    NSLog(@"%@", _mainParser.field);
    NSLog(@"%@", _mainParser.label);
    NSLog(@"%ld", (long)_mainParser.entityID);
    NSLog(@"%@", _mainParser.entityName);
    NSLog(@"%@", _mainParser.timeZone);
    NSLog(@"%@", _mainParser.units);
    NSLog(@"%@", _mainParser.parameters);
    NSLog(@"%ld", (long)_mainParser.param_Value);
    NSLog(@"%@", _mainParser.param_Name);
    NSLog(@"%ld", (long)_mainParser.start);
    NSLog(@"%@", _mainParser.startLabel);
    NSLog(@"%ld", (long)_mainParser.end);
    NSLog(@"%@", _mainParser.endLabel);
    NSLog(@"%ld", (long)_mainParser.value); 
}

The code for my Class parser:

- (void) go
{
    adapter = [[SBJsonStreamParserAdapter alloc] init];
    adapter.delegate = self;

    parser = [[SBJsonStreamParser alloc] init];
    parser.delegate = adapter;

    parser.supportMultipleDocuments = YES;

    NSString *url = myurl;

    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}

#pragma mark SBJsonStreamParserAdapterDelegate methods

- (void)parser:(SBJsonStreamParser *)parser foundArray:(NSArray *)array
{
    [NSException raise:@"unexpevted" format:@"Should not get here"];
}


- (void)parser:(SBJsonStreamParser *)parser foundObject:(NSDictionary *)dict
{
    solarStatus = [dict objectForKey:@"status"];
    fields = [dict objectForKey:@"fields"];
    type = [[dict objectForKey:@"fields"] valueForKey:@"type"];
    field = [[dict objectForKey:@"fields"] valueForKey:@"field"];
    label = [[dict objectForKey:@"fields"] valueForKey:@"label"];
    entityID = [[dict objectForKey:@"fields"] valueForKey:@"entityID"];
    entityName = [[dict objectForKey:@"fields"] valueForKey:@"entityName"];
    timeZone = [[dict objectForKey:@"fields"] valueForKey:@"entityName"];
    units = [[dict objectForKey:@"fields"] valueForKey:@"units"];
    parameters = [[dict objectForKey:@"fields"] valueForKey:@"parameters"];
    param_Value = [[[dict objectForKey:@"fields"] valueForKey:@"parameters"]valueForKeyPath:@"value"];
    param_Name = [[[dict objectForKey:@"fields"] valueForKey:@"parameters"]valueForKeyPath:@"name"];
    start = [[dict objectForKey:@"fields"] valueForKey:@"start"];
    startLabel = [[dict objectForKey:@"fields"] valueForKey:@"startLabel"];
    end = [[dict objectForKey:@"fields"] valueForKey:@"end"];
    endLabel = [[dict objectForKey:@"fields"] valueForKey:@"endLabel"];
    value = [[dict objectForKey:@"fields"] valueForKey:@"value"];



    NSLog(@"%@", solarStatus);
    NSLog(@"%@", fields);
    NSLog(@"%@", type);
    NSLog(@"%@", field);
    NSLog(@"%@", label);
    NSLog(@"%ld", (long)entityID);
    NSLog(@"%@", entityName);
    NSLog(@"%@", timeZone);
    NSLog(@"%@", units);
    NSLog(@"%@", parameters);
    NSLog(@"%ld", (long)param_Value);
    NSLog(@"%@", param_Name);
    NSLog(@"%ld", (long)start);
    NSLog(@"%@", startLabel);
    NSLog(@"%ld", (long)end);
    NSLog(@"%@", endLabel);
    NSLog(@"%ld", (long)value);

}
#pragma mark NSURLConnectionDelegate methods

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"Connection didReceiveResponse: %@ - %@", response, [response MIMEType]);
}



- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
    NSLog(@"Connection didReceiveAuthenticationChallenge: %@", challenge);

    NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceForSession];

    [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}



- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"Connection didReceiveData of length: %u", data.length);

    SBJsonStreamParserStatus status = [parser parse:data];

    if (status == SBJsonStreamParserError)
    {
        solarStatus = [NSString stringWithFormat:@"The parser encountered an error: %@", parser.error];
        NSLog(@"Parser error: %@", parser.error);

    } else if (status == SBJsonStreamParserWaitingForData) {
        NSLog(@"Parser waiting for more data");
    }
}



- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection failed! Error - %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}



- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
    NSLog(@"Connection finished");
}

The output of the class parser outputs the correct strings with actual DATA. But the issue is when output the same DATA in the Main View Controller, everything returns NULL or 0.

Like I said, I'm sure the issue lies with the main view controller loading before the class parser can even retrieve the DATA of the JSON object im obtaining.

Any help would be great!!!

Also I did some research and it seems I may need to implement a function to use an asynchronous call to the web service I am fetching DATA from but I am very new to such implementations.

OUTPUT

2013-05-27 16:18:26.580 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.585 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.585 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.586 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.586 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.586 PowerOneAuroraApp[14230:c07] 0
2013-05-27 16:18:26.586 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.587 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.587 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.587 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.588 PowerOneAuroraApp[14230:c07] 0
2013-05-27 16:18:26.588 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.588 PowerOneAuroraApp[14230:c07] 0
2013-05-27 16:18:26.603 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.603 PowerOneAuroraApp[14230:c07] 0
2013-05-27 16:18:26.603 PowerOneAuroraApp[14230:c07] (null)
2013-05-27 16:18:26.604 PowerOneAuroraApp[14230:c07] 0
2013-05-27 16:18:27.092 PowerOneAuroraApp[14230:c07] Connection didReceiveResponse: <NSHTTPURLResponse: 0x7539100> - application/json
2013-05-27 16:18:27.092 PowerOneAuroraApp[14230:c07] Connection didReceiveData of length: 2154
2013-05-27 16:18:27.094 PowerOneAuroraApp[14230:c07] SUCCESS
2013-05-27 16:18:27.095 PowerOneAuroraApp[14230:c07] (
        {
        end = 1369696440000;
        endLabel = "Mon May 27, 2013 5:14:00 PM MDT";
        entityId = 1167815;
        entityName = "Morone Residence";
        field = GenerationPower;
        label = now;
        parameters =         (
        );
        start = 1369696440000;
        startLabel = "Mon May 27, 2013 5:14:00 PM MDT";
        timeZone = "US/Mountain";
        type = instant;
        units = kilowatts;
        value = "0.229000000283";
    },
        {
        end = 1369696707064;
        endLabel = 20130527171827;
        entityId = 1167815;
        entityName = "Morone Residence";
        field = GenerationEnergy;
        label = today;
        parameters =         (
                        {
                name = "DataItem.now.maxCacheAge";
                value = 60;
            }
        );
        sampleEnd = 1369692840000;
        sampleEndLabel = 20130527161400;
        sampleStart = 1369634340000;
        sampleStartLabel = 20130526235900;
        start = 1369634400000;
        startLabel = 20130527000000;
        timeZone = "US/Mountain";
        type = window;
        units = "kilowatt-hours";
        value = "7.95501708984";
    },
        {
        end = 1369696707064;
        endLabel = 20130527171827;
        entityId = 1167815;
        entityName = "Morone Residence";
        field = GenerationEnergy;
        label = week;
        parameters =         (
                        {
                name = "DataItem.now.maxCacheAge";
                value = 60;
            }
        );
        sampleEnd = 1369692840000;
        sampleEndLabel = 20130527161400;
        sampleStart = 1369547940000;
        sampleStartLabel = 20130525235900;
        start = 1369548000000;
        startLabel = 20130526000000;
        timeZone = "US/Mountain";
        type = window;
        units = "kilowatt-hours";
        value = "16.60800170898";
    },
        {
        end = 1369696707064;
        endLabel = 20130527171827;
        entityId = 1167815;
        entityName = "Morone Residence";
        field = GenerationEnergy;
        label = month;
        parameters =         (
                        {
                name = "DataItem.now.maxCacheAge";
                value = 60;
            }
        );
        sampleEnd = 1369692840000;
        sampleEndLabel = 20130527161400;
        sampleStart = 1367387940000;
        sampleStartLabel = 20130430235900;
        start = 1367388000000;
        startLabel = 20130501000000;
        timeZone = "US/Mountain";
        type = window;
        units = "kilowatt-hours";
        value = "269.87199401855";
    },
        {
        end = 1369692840000;
        endLabel = "Mon May 27, 2013 4:14:00 PM MDT";
        entityId = 1167815;
        entityName = "Morone Residence";
        field = GenerationEnergy;
        label = lifetime;
        parameters =         (
        );
        start = 1369692840000;
        startLabel = "Mon May 27, 2013 4:14:00 PM MDT";
        timeZone = "US/Mountain";
        type = instant;
        units = "kilowatt-hours";
        value = "1609.48400878906";
    }
)
2013-05-27 16:18:27.097 PowerOneAuroraApp[14230:c07] (
    instant,
    window,
    window,
    window,
    instant
)
2013-05-27 16:18:27.098 PowerOneAuroraApp[14230:c07] (
    GenerationPower,
    GenerationEnergy,
    GenerationEnergy,
    GenerationEnergy,
    GenerationEnergy
)
2013-05-27 16:18:27.098 PowerOneAuroraApp[14230:c07] (
    now,
    today,
    week,
    month,
    lifetime
)
2013-05-27 16:18:27.098 PowerOneAuroraApp[14230:c07] 124196320
2013-05-27 16:18:27.099 PowerOneAuroraApp[14230:c07] (
    "Morone Residence",
    "Morone Residence",
    "Morone Residence",
    "Morone Residence",
    "Morone Residence"
)
2013-05-27 16:18:27.099 PowerOneAuroraApp[14230:c07] (
    "Morone Residence",
    "Morone Residence",
    "Morone Residence",
    "Morone Residence",
    "Morone Residence"
)
2013-05-27 16:18:27.099 PowerOneAuroraApp[14230:c07] (
    kilowatts,
    "kilowatt-hours",
    "kilowatt-hours",
    "kilowatt-hours",
    "kilowatt-hours"
)
2013-05-27 16:18:27.104 PowerOneAuroraApp[14230:c07] (
        (
    ),
        (
                {
            name = "DataItem.now.maxCacheAge";
            value = 60;
        }
    ),
        (
                {
            name = "DataItem.now.maxCacheAge";
            value = 60;
        }
    ),
        (
                {
            name = "DataItem.now.maxCacheAge";
            value = 60;
        }
    ),
        (
    )
)
2013-05-27 16:18:27.105 PowerOneAuroraApp[14230:c07] 124196576
2013-05-27 16:18:27.105 PowerOneAuroraApp[14230:c07] (
        (
    ),
        (
        "DataItem.now.maxCacheAge"
    ),
        (
        "DataItem.now.maxCacheAge"
    ),
        (
        "DataItem.now.maxCacheAge"
    ),
        (
    )
)
2013-05-27 16:18:27.106 PowerOneAuroraApp[14230:c07] 124196720
2013-05-27 16:18:27.106 PowerOneAuroraApp[14230:c07] (
    "Mon May 27, 2013 5:14:00 PM MDT",
    20130527000000,
    20130526000000,
    20130501000000,
    "Mon May 27, 2013 4:14:00 PM MDT"
)
2013-05-27 16:18:27.106 PowerOneAuroraApp[14230:c07] 124196784
2013-05-27 16:18:27.106 PowerOneAuroraApp[14230:c07] (
    "Mon May 27, 2013 5:14:00 PM MDT",
    20130527171827,
    20130527171827,
    20130527171827,
    "Mon May 27, 2013 4:14:00 PM MDT"
)
2013-05-27 16:18:27.107 PowerOneAuroraApp[14230:c07] 124196848
2013-05-27 16:18:27.107 PowerOneAuroraApp[14230:c07] Parser waiting for more data
2013-05-27 16:18:27.107 PowerOneAuroraApp[14230:c07] Connection finished
jsetting32
  • 1,632
  • 2
  • 20
  • 45

2 Answers2

1

You shouldn't be doing this. You will never be able to get the information from the URL before you want to read it unless you make it synchronous which means you would have ur UI stuck in the viewdidload until its finished which is a terrible practice.

I'm not familiar with SBJSON but it most probably has either a delegate method call or a completition handler block, you should handle the retrieved information there.

Edit: Actually my bad, I didn't realize you are using NSURLConnection to get the json data. Plus I can see several other weird things in your code.

All you have to do is check the apple documentation here and implement: connectionDidFinishLoading in your main controller.

After you get the response of the JSON data you should give it to your parser and then you can use the information.

In this code i cant see your connection delegate nor anywhere you are feeding this data to your parser.

Like this:

SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSError *error = nil;
NSArray *jsonObjects = [jsonParser objectWithString:jsonString error:&error];
[jsonParser release], jsonParser = nil;

But in the log it appears so i assume you are doing that correctly.

Check the log,

Connection didReceiveResponse:

appears AFTER you request the data, so theres nothing before this call appears. Move whatever code you are using to parse the info to that method.

Pochi
  • 13,391
  • 3
  • 64
  • 104
  • This is was what I figured I had to do but I am very new to JSON objects and dealing with these sort of callbacks and completion handler blocks. If anyone has any examples in how to do this.... I'd greatly appreciate it!!! I have referenced to the SBJSON api documentations but like I said, I'm sorta new and an example to get me on track would be very helpful. Hopefully someone else has had the same issue and solved it so I wont have to take hours if not days to solve this issue. – jsetting32 May 28 '13 at 00:53
  • check edit, since this is not your full code im not sure how you are doing the things, but i think the fix is very simple. (move your code from whever it is to the didfinishloading delegate call) – Pochi May 28 '13 at 01:36
1

Please look at the TweetStream example project for how to parse JSON asynchronously with SBJson: https://github.com/stig/json-framework/blob/master/Examples/TweetStream/TweetStream/TweetStreamViewController.m - it is absolutely supported.

Stig Brautaset
  • 2,602
  • 1
  • 22
  • 39