unable to parse JSON data from a NSURLConnection response - iphone

I am getting a server response of the form:
results are:{
AverageMark = 40;
"Grade A" = 10;
"Grade B" = 20;
"Grade C" = 30;
"Grade D" = 20;
MaxMark = 99;
MinMark = 44;
ProfileGrade = "";
ProfileMark = 1;
}
However I am unable to save the response data into an Array.
This is my code inside didReceiveResponse:
{
NSString *jsonString = [[NSString alloc] initWithString:responseData];
NSArray *jsonResults = [jsonString JSONValue];
NSLog(#"results are:%#",jsonResults); //this log is shown above
for (int i=0; i<[jsonResults count]; i++)
{
NSDictionary *AllData=(NSDictionary *)[jsonResults objectAtIndex:i]; //Program is crashing here--//
NSMutableArray *DataArray=[[NSMutableArray alloc]init];
NSString *avgMarkString;
avgMarkString=(NSString *)[AllData objectForKey:#"MaxMark"];
[DataArray addObject:avgMarkString];
}
}
I want to save the response data into the array called "DataArray". But the program is crashing.
What am I doing wrong?

You likely don't have the complete data yet in -connection:didReceiveResponse:. Create an instance variable or property of the type NSMutableData and initialize the data ivar or property in
-connection:didReceiveResponse: if you get a valid statusCode (between 200-299 should be ok). Use appendData: on the data object in the -connection:didReceiveData: delegate method. Finally in -connectionDidFinishLoading: the data is complete and can be parsed into JSON.
Alternatively you could just use the AFNetworking library. The library got some convenience methods for dealing with XML, JSON, images, etc...
Read the following page to get an introduction into the capabilities of AFNetworking: http://engineering.gowalla.com/2011/10/24/afnetworking/
Some example code from one of my own projects for downloading using a queue using NSURLConnectionDelegate methods. The URL Request objects are a custom subclass of NSURLConnection for some block "callbacks":
#pragma mark - URL connection delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSRange range = NSMakeRange(200, 99);
if (NSLocationInRange(httpResponse.statusCode, range));
{
self.data = [[NSMutableData alloc] init];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_data appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// inform caller that download is complete, provide data ...
if (_request.completionHandler)
{
_request.completionHandler(_data, nil);
}
[self removeRequest:_request];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
DLog(#"%#", error);
// inform caller that download failed, provide error ...
if (_request.completionHandler)
{
_request.completionHandler(nil, error);
}
[self removeRequest:_request];
}

that isn't json, try having a look at this http://json.org/example.html

Given JSON response is invalidate. Validate your JSON response here.

Related

implement Asynchronous method using NSURLConnection [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
MY Problem is that i connected connection with the delegate but it is not interrupting its delegate method. I want to fetch address for my annotation and display it in annotation view. i successfully fetched the address but the mapview loading takes time, that is why i used the NsConnection Method . Please help me if i have made any mistake.
CLLocationCoordinate2D coordinate;
coordinate.latitude = 28.6667;
coordinate.longitude = 77.2167;
clusterMap.region = MKCoordinateRegionMakeWithDistance(coordinate, 5000, 5000);
self.blocks = 4;
self.minimumClusterLevel = 100000;
// super.delegate = self;
zoomLevel = clusterMap.visibleMapRect.size.width * clusterMap.visibleMapRect.size.height;
NSMutableArray *pins = [[NSMutableArray alloc]init];
for(int i =0 ; i < 50; i++)
{
CGFloat latDelta = rand()*0.125/RAND_MAX - 0.02;
CGFloat lonDelta = rand()*0.130/RAND_MAX - 0.08;
newCoord.latitude = coordinate.latitude+latDelta;
newCoord.longitude = coordinate.longitude+lonDelta;
NSString *urlString = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=false",newCoord.latitude, newCoord.longitude];
// NSLog(#"Is%# main thread", ([NSThread isMainThread] ? #"" : #" NOT"));
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
[connection start];
customannView = [[AnnotationView alloc]initWithLatitude:newCoord.latitude andLongitude:newCoord.longitude];
// customannView.title = [NSString stringWithFormat:#"Pin %i",i];
customannView.title =locationString;
customannView.subtitle = [NSString stringWithFormat:#"Pin %i",i];
customannView.coordinate = newCoord;
customannView.imgName = #"bookmark1.png";
[pins addObject:customannView];
[connection cancel];
}
[self addAnnotations:pins];
UILongPressGestureRecognizer *dropPin = [[UILongPressGestureRecognizer alloc] init];
[dropPin addTarget:self action:#selector(handleLongPress:)];
dropPin.minimumPressDuration = 0.5;
[clusterMap addGestureRecognizer:dropPin];
}
// [self performSelector:#selector(mapViewWillStartLoadingMap:) withObject:nil afterDelay:0.01];
UILongPressGestureRecognizer *dropPin = [[UILongPressGestureRecognizer alloc] init];
[dropPin addTarget:self action:#selector(handleLongPress:)];
dropPin.minimumPressDuration = 0.5;
[clusterMap addGestureRecognizer:dropPin];
}
#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
// A response has been received, this is where we initialize the instance var you created
// so that we can append data to it in the didReceiveData method
// Furthermore, this method is called each time there is a redirect so reinitializing it
// also serves to clear it
[responseData setLength:0];
NSLog(#"Response :: %#",responseData);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// Append the new data to the instance variable you declared
[responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
// Return nil to indicate not necessary to store a cached response for this connection
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// The request is complete and data has been received
// You can parse the stuff in your instance variable now
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// The request has failed for some reason!
// Check the error var
}
why are you doing
[connection cancel];
because it cancel the process before hitting the delegates.Remove that line and the code will work
The difficulty with your approach is that you are spawning a number of NSURLConnections and try then to handle with one delegate.
In order to figure out which connection and response data is associated to which latitude/longitude and response data object in your delegate method you would need to obtain the original request from the connection and then parse the URL which contains that info. This is cumbersome at least.
I would suggest to create a class (or use a third party library) that encapsulates one NSURLConnection request, the response data and possibly other state info. Purposefully, this class has a completion block where it becomes easy to associate the latitude/longitude and response data from the call site with each completion handler of a finished connection.

Response from server coming as null in the client(IOS) on async call in app development

I am making an asynchronous call to the server from the client, and printing data on the server.
But the response which i get at the client is coming as null
My response retrieval part is as under:-
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
NSLog(#"connection did receive response");
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere
if(!receivedData)
{
receivedData = [NSMutableData data];
}
[receivedData appendData:data];
NSLog(#"connection did receive data");
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// receivedData is declared as a method instance elsewhere
NSString *responseFromServer = [[NSString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"connection did finish load");
NSLog(#"response from the server=%#", responseFromServer);
}
So 'responseFromServer' value is coming as null.
Can anybody tell me where am i going wrong.
Thanks in advance.
If you're not strongly referencing receivedData, you may want to start doing it
receivedData = [NSMutableData data]; is an autoreleased object. Make sure that receivedData is a strong or retained property, then set it like so self.receivedData = [NSMutableData data];
It's a possibility that receivedData is getting autoreleased before the final connectionDelegate method fires, thus the responseString is using nil data in the initWithData method
Are you sure that receivedData contains UTF8 encoded data = string? initWithData:encoding: documentation ...
Return Value
An NSString object initialized by converting the bytes in data into Unicode characters using encoding. The returned object may be different from the original receiver. Returns nil if the initialization fails for some reason (for example if data does not represent valid data for encoding).
... as you can see, it returns nil if initialization fails.

While downloading an HTML file show a static text and running points (Loading. .. ...)

In my app I download an HTML file from a server and check if an image is currently on the website and set a status to a label when the image was found. All works great but I like to
show the user a Loading status label while the app is downloading the file. It works with static text but how can I show running points after the Loading text? I like to see: Loading > Loading. > Loading.. > Loading... > Loading > and so on (I don't need an exact progress bar)
Code:
- (void)viewDidLoad
{
[super viewDidLoad];
platzStatusLabel.text = #"Loading";
if (myConnection == nil) {
myData = [NSMutableData new];
NSString *urlString = [NSString stringWithFormat:#"http://www.myURL.com"];
myConnection =[NSURLConnection connectionWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:urlString]]
delegate:self];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *stringToLookup = [[NSString alloc]initWithData:myData encoding:NSASCIIStringEncoding];
if ([stringToLookup rangeOfString:#"image_green"].location != NSNotFound){
platzStatusLabel.text = #"Course is open.";
} else {
platzStatusLabel.text = #"Course is closed.";
}
[self initializeVariablesAgain];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[myData appendData:data];
}
- (void) initializeVariablesAgain {
myData = nil;
myConnection = nil;
}
Why not start a UIActivityIndicator (this circly thing that highlights) upon creation of the request and stop it in didFinishLoading?
Or start and stop an NSTimer that iterates through your several strings in the same fashion.
Lastly, you could iterate through your different strings in didReceiveData.
Cheers
Update your counter (file size downloaded updates) in
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
eg.
[myData appendData:data];
self.myCountInBytesOfDownloadProgress = [myData length];

Add UIImage to NSMutableArray through Delegate Method S3

I'm trying to get AWS S3 to go get images from an S3 bucket, the code below is in two parts. The first (I think) creates the get object request after initiating the array to put the object in (arrayImages, it gets the count from arrayPointer). The second is the delegate method that puts the object (data) in arrayImages once it finishes. I would assume that each time the delegate method is called it would add a new object. Something is wrong here:
-(void)gets3ImageArray
{
if (arrayImages == nil) {
arrayImages = [[NSMutableArray alloc] initWithCapacity:[arrayPointer count]];
}
else
{
[arrayImages removeAllObjects];
}
AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];
for (NSString *name in arrayPointer){
#try {
S3GetObjectRequest *gor = [[S3GetObjectRequest alloc]initWithKey:name withBucket:[Constants pictureBucket]];
[gor setDelegate:self];
[s3 getObject:gor];
}
#catch (AmazonClientException *exception) {
[Constants showAlertMessage:exception.message withTitle:#"Download Error"];
}
}
}
-(void)request:(AmazonServiceRequest *)request didReceiveData:(NSData *)data
{
UIImage *myImage = [[UIImage alloc] initWithData:data];
if(!myImage)
{
NSLog(#"NO IMAGE");
[arrayImages addObject:[UIImage imageNamed:#"placeholder.png"]];
}
else
{
[arrayImages addObject:[UIImage imageWithData:data]];
}
you need to append the data received in your ...
-(void)request:(AmazonServiceRequest *)request didReceiveData:(NSData *)data
...method as it can be called multipled times. declare a NSMutableData *responseData in your header file and append the data until your didCompleteWithResponse delegate is called.
[responseData appendData:data];
Make sure you alloc the mutable data before you call the AmazonS3Client.
responseData = [[NSMutableData data] retain]; // or autorelease or not depending on ARC etc
You will likely need to implement all these delegates: (but the amazon docs should be able to confirm)
didReceiveResponse: Sent when body data has been read. May be called multiple times.
didReceiveData: Sent when body data has been read. May be called multiple times.
didCompleteWithResponse: Sent when the entire response has been read and processed. The object sent to this method is the same object returned when making a non-asynchronous request.
didSendData: Sent when the request transmitted data.
didFailWithError: Sent when there was a basic failure with the underlying connection.
didFailWithServiceException: Sent when the service responded with an error message.

Multiple NSURLConnection & NSRunLoop

I am trying to speed up my application download speed. I used Asynchronous NSURLConnection to download contents from the server, it was working fine with one connection.
I use the code from this post to implement multiple delegate objects. Multiple NSURLConnection delegates in Objective-C
When I created 2 NSURLConnection objects, each one is trying to download different files.
The callback didReceiveData routine was called but the it only received data of the first NSURLConnection object until the first connection was done then it started to receive the data from the second NSURLConnection. I want these two connections to receive data at the same time,what should I do? Here is my current code.
-(IBAction) startDownloadClicked :(id) sender
{
while (bDownloading)
{
int nCurrentCon = 0;
while (nCurrentCon < 2)
{
[self downloadAFile:[filenameArray objectAtIndex:nCurrentCon]];
nCurrentCon++;
}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
}
}
- (void) downloadAFile: (NSString*) filename
{
NSString* urlstr = #"ftp://myftpusername:password#hostname";
NSURLRequest* myreq = [NSURLRequest requestWithURL:[NSURL URLWithString:urlstr]];
DownloadDelegate* dd = [[DownloadDelegate alloc] init]; //create delegate object
MyURLConnection* myConnection = [[MyURLConnection alloc] initWithRequest:myreq delegate:dd
startImmediately:YES];
}
Then in my Delegate Object, I implemented these routines
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receiveBuffer setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"receiving data for %#", targetFileName); //the file name were set when this delegate object is initialized.
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Download Failed with Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"File %# - downloaded.", targetFileName);
}
Your code looks okay. I have a similar setup that works successfully (although there seems to be a limit of four concurrent conections).
The main difference between your and my code is that you use FTP while I use HTTP. Why don't you try it with HTTP connections just to see whether you have run into a restriction of FTP connections on the iPhone?