iPhone unable to parse JSON results from YELP - iphone

I'm attempting to parse validated JSON from a yelp search result.
This correctly spits out the json as expected (confirmed in simulator browser and my own).
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *dump = [[[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding] autorelease];
NSLog(#"Did Recieve data: %#", dump);
[JSONData appendData:data];
}
But when my connection finishes loading I'm having a hard time extracting the results and parsing the data:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Connection Did Finish Loading");
NSError *error = nil;
id cureLocations = [[CJSONDeserializer deserializer] deserializeAsDictionary:JSONData error:&error];
[JSONData release];
NSLog(#"Connection finished loading: %#", error);
}
I get: Connection finished loading: Error Domain=CJSONDeserializerErrorDomain Code=-11 "The operation couldn’t be completed. (CJSONDeserializerErrorDomain error -11.)"
I switched to TouchJSON from SBJSON because I wasn't able to extract it from that framework either. I've attempted loading it into Dictionaries and Arrays with null as the result. At this point I've been banging my head on the keyboard for hours and would greatly appreciate any input.
JSON sample
Update:
I am a dummy. I hadn't initialized JSONData. Please accept my apologies for wasting your time and thanks for your suggestions.

SBJSON is a pretty decent and well known parser. If it didn't parse your input, you'd probably assume it's because the input was genuinely bad. If TouchJSON isn't parsing it either, the input is definitely bad. So there's something going on with you JSONData object that's dodgy.
I would suggest you print out your JSON data to the console in your connectionDidFinishLoading method and try re-validating it. See what's actually in the data object you're passing to CJSON.

Ugh, after further review of the application it seems that I rushed to copy my samples into this project and forgot to initialize JSONData:
self.JSONData = [[[NSMutableData alloc] init]autorelease];
Then I updated my didReceiveData method:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[[self JSONData] appendData:data];
}
And everything is now working as expected. This is the second time I've run into this error. I guess I always expected the debugger to pick it up. Thanks for everyones time and assistance.

Related

iPhone app crashes randomly with exc_bad_access

I have an app with four tabs. In each tab I connect to remote server using nsurlconnection, fetches the response and display accordingly. While testing the app, I get crashes randomly. If I try to reproduce the crash again I do not get crash. I do not understand what is root cause of the crash. I enable NSZombie,symbolicated crash logs,checked the memory leak but no luck.
I started the project in Xcode 3 and now I imported same project to Xcode 4.2, so are there any issues with compatibility of Xcode?
And I use the same name for nsurlconnection in all tabs like
In Tab 1 I defined nsurlconnection as conn and Tab 2 defined nsurlconnection as conn.
Does this definition causes any issue?
Please help me solve this random crashes
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: url];
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(label != nil){
progressView = [[ProgressView showHUDAddedTo:self.tabBarController.view animated:YES] retain];
progressView.labelText = label;
}
[request release];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"didReceiveresponse");
if ([response isKindOfClass: [NSHTTPURLResponse class]]) {
if([(NSHTTPURLResponse *)response statusCode] == 200){
}
else{
//show Connection Error Alert
}
}
responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"didReceiveData");
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[progressView hide:YES];
NSLog(#"didFail");
//show failed alert
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"didfinish loading");
if([responseData length] > 0)
{
//handles response data
}
}
My guess without seeing code, would be that in a tab your making an NSURLConnection and doing something with the result when it completes. If you change tab before the result is returned then it is causing it to crash.
You need to cancel the NSURLConnection when viewDidDisappear, or make sure that whatever code is run on completion of it doesn't contain anything that would cause a crash if the tab isn't visible (like setting a labels text).
The way I handle this, is have a separate class that performs the URL requests that sends a notification when it's complete. That way in your viewDidAppear method you set your viewController to listen for the notifications, and in the viewDidDisapper method you stop listening for the notifications. So if your view isn't visible when the URL request finishes, the notification is fired but nothing happens.
Could you provide the output of the console? It seems not to be an error from Xcode.
These type of error usually appear when you try to access a deallocated object.
i am sure you have tried Instruments with memory leak. give a try with instruments with zombie tool, you can find it easily in instruments library.
run your code with this tool and if this crash is because of any zombie object then you will easily able to detect the location.
it has helped me few times.

EXC_BAD_ACCESS error with RestKit in didReceiveResponse method

I can't get rid of a EXC_BAD_ACCESS error in RestKit. I suspect its because I have an ARC project and may be releasing the request or response variable too many times, but I've spent hours on this and am not sure.
My problem sounds similar to this post, but I'm not sure where in my code to make a similar change.
My implementation file has a straightforward method to post the new object to the server. All the mapping logic is down within the implementation file for the NSObject below:
-(void) createMeeting
{
NSString* baseUrl = #"https://myapp.appspot.com/api/meeting/?format=json&username=testuser#test.com&api_key=f8s9df8as8df9s8d97";
RKObjectManager* rkoManager = [RKObjectManager objectManagerWithBaseURLString:baseUrl]; [NewMeetingRK initMap:rkoManager];
NewMeetingRK *newmtg = [NewMeetingRK alloc];
newmtg.leader = self.leaderEmail.text;
newmtg.startdate = [sqliteformatter stringFromDate:bdate];
newmtg.enddate = [sqliteformatter stringFromDate:edate];
[[RKObjectManager sharedManager] postObject:newmtg delegate:self];
And it successfully begins requestDidStartLoad:(RKRequest *)request
However it then crashes in RKResponse.m on the second to last line below (if ([[_request delegate] respondsToSelector:... with a EXC_BAD_ACCESS error.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
RKResponseIgnoreDelegateIfCancelled();
RKLogDebug(#"NSHTTPURLResponse Status Code: %ld", (long) [response statusCode]);
RKLogDebug(#"Headers: %#", [response allHeaderFields]);
_httpURLResponse = [response retain];
[_request invalidateTimeoutTimer];
if ([[_request delegate] respondsToSelector:#selector(request:didReceiveResponse:)]) {
[[_request delegate] request:_request didReceiveResponse:self];
}
}
Any ideas to help me? Thanks much.
EXC_BAD_ACCESS happens when a message is sent to an object that has been released.
You should pay attention to _request delegate object. NSZombieEnabled break point might help you too. How to enable zombie objects

Which delegate of NSURLConnection to use

I have a doubt regarding downloading data from a web service. One way is to download it in a single line mentioned below.
NSString *returnString = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:urlrequest returningResponse:nil error:nil] encoding:NSUTF8StringEncoding];
And the other way to get it is via connectionDidFinishLoading
[..]
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:urlrequest delegate:self];
NSHTTPURLResponse *response;
[NSURLConnection sendSynchronousRequest: urlrequest returningResponse: &response error: nil];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
else
{
NSLog(#"theConnection is NULL");
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length: [webData length] encoding:NSUTF8StringEncoding];
}
Is there any difference between these two? NSURLConnection delegate method is not called when I use a separate class to parse the response.
You're using sendSynchronousRequest:returningResponse:error: which does not call any delegates methods because it doesn't need to: when you call it, the main thread stops until the request is finished and you get the response.
If you want to make an asynchronous request, use connectionWithRequest:delegate:. I recommend to always do asynchronous responses since the synchronous request blocks the main thread and your UI can't respond during that time. Animations will become interrupted. Scrolling becomes jerky. If you do want to use synchronous requests you should do it in a background thread.
The -sendSynchronousRequest:returningResponse:error: method blocks the main-thread (whenever it runs on the main-thread of course, since it's possible to run this method from any other thread, but I believe this is not recommended).
The methods using the delegates are asynchronous, the methods will fire and the results will (at some point in the future) be returned in the delegate methods. This gives the user a more smooth experience, since the main-thread will not be blocked.
Edit: personally I hardly ever use the -sendSynchronousRequest:returningResponse:error: method for the aforementioned reasons. Most of the time I use this method when I need to build something quickly, for example a proof-of-concept. I guess one could use the method for small downloads, yet if a timeout occurs (because for some reason the server is down) the whole UI will be blocked for (I believe) 2 minutes, which would be very annoying for the enduser.
An excellent demonstration to clarify your doubt is available in apple sample apps.You can refer Apple's sample app for a better understanding of asynchronous request and parsing data in separate class.

NSURLConnection get URL

how i get the URL inside the following method ??
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection
Hey there's a comment from Mihai Damian that worked for me:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSURL *myURL = [[connection currentRequest] URL];
Cheers
You ought to be able to do theConnection.request.URL, but you can't. Annoying, isn't it?
The simplest way is to just save the URL (or the whole NSURLRequest) that you were loading. If you're using multiple connections, you can store them in a dictionary. Note that -[NSMutableDictionary setObject:forKey:] copies keys, and NSURLConnections are not copyable; the workaround is to use CFDictionarySetValue instead:
CFDictionarySetValue((CFMutableDictionaryRef)dict, connection, request);
Of course the above answers work, and I am looking for similar solution.
Just found that NSLog([connection description]); prints something like:
< NSURLConnection: 0x9129520, http://google.com>
So it is possible to parse the string returned by [connection description], and get the url from the connection, though it is kind of dirty.
You can get URL like this
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
for more information you van read here.
Here is my suggestion
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
self.rssFeedConnection = nil;
NSLog(#"connectionDidFinishLoading url : %# ", connection.originalRequest.URL);
}
In Swift 2.0 iOS 9 you can do it like:
func connectionDidFinishDownloading(connection: NSURLConnection, destinationURL: NSURL) {
print(connection.currentRequest.URL!)
}

iPhone JSON object releasing itself?

I'm using the JSON Framework addon for iPhone's Objective-C to catch a JSON object that's an array of Dictionary-style objects via HTTP. Here's my connectionDidFinishLoading function:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[loadingIndicator stopAnimating];
NSArray *responseArray = [responseString JSONValue]; // Grab the JSON array of dictionaries
NSLog(#"Response Array: %#", responseArray);
if ([responseArray respondsToSelector:#selector(count)]) {
NSLog(#"Returned %# items", [responseArray count]);
}
[responseArray release];
[responseString release];
}
The issue is that the code is throwing a EXC_BAD_ACCESS error on the second NSLog line. The EXC_BAD_ACCESS error I think indicates that the variable got released from memory, but the first NSLog command works just fine (and shows that the data is all there); it seems that only when calling the count message is causing the error, but the respondsToSelector call at least thinks that the responseArray should be able to respond to that message. When running with the debugger, it crashes on that second line, but the stack shows that the responseArray object is still defined, and has 12 objects in it (so the debugger at least is able to get an accurate count of the contents of that variable).
Is this a problem with the JSON framework's creation of that NSArray, or is there something wrong with my code?
count returns an NSUInteger, not an object. Per the Apple Documentation you should use %lu and cast to unsigned long in this case instead to display it:
NSLog(#"Returned %lu items", (unsigned long)[responseArray count]);
With %#, NSLog() tries to interpret the value as a pointer to an object and to send a description message to it.
It is highly unlikely that there is accidentally a valid object at that memory location, so the code is bound to fail badly or show unpredictable results.
In addition to what gf and Nikilai said, [responseArray release]; over releases
If those guys got their method naming right, NSArray *responseArray = [responseString JSONValue]; returns an autoreleased instance.
Simple typo: Your format string in the second NSLog contains an %# instead of %d.