0

By going to a url test.com/test.cfm I am able to output the following:

{"COLUMNS":["OBJID","USERNAME","USERPASSWORD","USERFNAME","USERMI","USERLNAME","COMPANY","TBLCOMPANYID","TBLTITLE","USERADDRESS1","USERADDRESS2","USERCITY","USERSTATE","USERZIP","USERSIGNATUREFILE","USERBUSINESSNUMBER","USERBUSINESSEXT","USERFAXNUMBER","USERCELLNUMBER","USEROTHERNUMBER","USEREMAIL1","USEREMAIL2","USEREMAIL3","DEFAULTPROJECTID","SIGNATURE","SIGNATUREUPLOADBY","SORTORDER","DISABLESTATUS","UUID","SITEID","PROGRAMID"],
"DATA":[[1,"test",11214.0,"admin","","admin","adf Inc.",1,1,"admin","","","California","","","",null,"","","","admin@test.com","","",0,null,null,0,false,"468373c5-1234-1234-1234-3133a2bb1679",62,1]]}

To iterate through this I will first need to get the data using this?

NSMutableData *receivedData;
    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL     URLWithString:@"test.com/test.cfm"]
                                          cachePolicy:NSURLRequestUseProtocolCachePolicy
                                      timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:receivedData];
if (theConnection) {
    // Create the NSMutableData to hold the received data.
    // receivedData is an instance variable declared elsewhere.        
    NSLog(@"test = %@",receivedData);
} else {
    // Inform the user that the connection failed.
} 

Am I on the right track? The output says null...

terezzy
  • 243
  • 1
  • 3
  • 8

1 Answers1

1

You've not assigned anything to receivedData; it'll either be nil (under ARC) or an undefined value which may or may not be nil (under non-ARC). You've created an object that could be used to initiate a URL connection but done nothing with it. You're also probably not getting a valid NSURL because you've failed to specify the URI scheme (ie, the http://).

Probably the easiest thing to do (assuming at least iOS 5 and/or OS X v10.7) would be to use NSURLConnection's +sendAsynchronousRequest:queue:completionHandler: and then NSJSONSerialization to parse the result. E.g.

NSURLRequest *theRequest = 
            [NSURLRequest 
                 requestWithURL:[NSURL URLWithString:@"http://test.com/test.cfm"]
                    cachePolicy:NSURLRequestUseProtocolCachePolicy
                timeoutInterval:60.0];

// or just use [NSURLRequest requestWithURL:[NSURL ...]], since the
// protocol cache policy and a 60s timeout are the default values anyway

[NSURLConnection
   sendAsynchronousRequest:theRequest
   queue:[NSOperationQueue mainQueue]
   completionHandler:
        ^(NSHTTPURLResponse *urlResponse, NSData *data, NSError *error)
        {
            // catch all for connection errors...
            if(
                (urlResponse.statusCode < 200) ||
                (urlResponse.statusCode >= 300) || // bad status code, e.g. 404
                error || // error is non-nil would imply some other error
                ![data length] // data returned was empty
             )
             {
                  // report some sort of connection error
                 return;
             }

             NSError *jsonError = nil;
             id <NSObject> returnedJSONObject =
                [NSJSONSerialization
                          JSONObjectWithData:data options:0 error:&jsonError];
             if(jsonError)
             {
                   // server returned unintelligible JSON...
                   return;
             }

             NSLog(@"Got object %@", returnedJSONObject);

             // then, e.g.
             if(![jsonObject isKindOfClass:[NSDictionary class]])
             {
                 // server didn't return a dictionary
                 return;
             }

             NSArray *columns = [jsonObject objectForKey:@"COLUMNS"];
             if(![columns isKindOfClass:[NSArray class]])
             {
                  // server returned no COLUMNS object, or that
                  // object wasn't an array
                  return;
             }

             NSLog(@"columns are %@", columns);

             /* etc, etc */
        }];

The class type checking stuff quickly gets quite tedious if you don't find a way to automate it but that's all validation stuff not directly related to your question.

What the above achieves is that it sends an asynchronous (ie, non-blocking) request for the contents of the URL. Results are accumulated on the main queue (ie, the same place you'd normally do user interactions). Once that entire HTTP operation is complete the code you specified at the bottom is called and that validates and parses the response. It does so synchronously so will block but that's not worth worrying about unless profiling shows it's worth worrying about.

The built-in parser is used for the JSON and everything down to 'Got object' is really just ensuring that the fetch and parse succeeded. It may not be complete — if you can think of anything else that might go wrong then don't assume I've ignored it on purpose.

At that point you just have an object of unknown type but it'll normally be a dictionary or an array because of the fundamentals of JSON. So the example code tests that it really is a dictionary then uses the normal NSDictionary interface to obtain an object for the 'COLUMNS' key. If you attempted to call objectForKey: on an array you'd raise an exception since arrays don't implement that method.

It's then fairly rote — the code checks that the object stored as 'COLUMNS' was an array. Per the JSON rules it could have been another dictionary or a string or one of a few other things. Possibly of interest is that the code calls isKindOfClass: to test that an object was found and that it was an array in a single call; that works because it's explicitly permissible to send any message to nil and the result will always be nil, which looks the same as a BOOL NO.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • I'm getting sent to the jsoError if statement. when I go to http://test.com/test.cfm, I am able to generate the above format... – terezzy Oct 30 '12 at 23:29
  • Try `NSLog`ging the error — it should give a description of the problem that'll help you to diagnose further. – Tommy Oct 30 '12 at 23:37
  • I have the returnedJSONObject, I can output it to the log. Now how do I turn this NSObject returnedJSONObject into a NSDictionary, I tried this... `NSDictionary *dataDict = [returnedJSONObject objectForKey:@"DATA"];` There's an error `No known instance method for selector objectForKey` – terezzy Oct 30 '12 at 23:58
  • What type of object is it at the minute? It should be whatever the top-level object in your JSON was but you can log `[returnedJSONObject class]` to get an explicit record. – Tommy Oct 31 '12 at 00:10