why nsurldelegates method are not called when json parsing in iphone - iphone

I am developing one iphone application from google places API. For that I am doing JSON parsing for getting data.
For JSON parsing I have made one class and in which I'm writting these methods
in JsonParse.m file following methods are written:
- (void)initWithURLString:(NSString *)aURLString parameter:(UIViewController *)viewController
{
NSURL *url = [NSURL URLWithString:aURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
connection=[[NSURLConnection alloc] initWithRequest:request delegate:viewController];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
label.text=[NSString stringWithFormat:#"error in the connection %#",[error description]];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responsestring=[[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"response string is %#",responsestring);
NSError *error;
SBJSON *json=[[SBJSON new]autorelease];
NSMutableDictionary *response=[NSMutableDictionary dictionary];
response=[json objectWithString:responsestring error:&error];
NSLog(#"values in the dictionary is %#",[response valueForKey:#"results"]);
}
And I am calling the method from the viewcontroller class as below:
JsonParse *obj=[[JsonParse alloc] init];
[obj initWithURLString:urlstr parameter:self];
But when I am debugging only initwithurl method is called, other connection delegate methods are not called.
Previously I have written the methods in the same class means in the viewcontroller class at that time every method was called and I was able to prase data.
I have written this method in seperate class because in the same viewcontroller class I want to parse data multiple times (more that 1 time with different urls).
Does anyone know why these methods are not called or how can I parse multiple times in the same class? Any tutorial or sample code for that?

In :
// the delegate must be self
connection=[[NSURLConnection alloc] initWithRequest:request
delegate:viewController];
The delegate should be self in order for these methods to get called, because these methods are implemented in JsonParse.

Related

Objective-C JSON Parse don't work in other classes

I have a strange problem with the NSURLConnectionDataDelegate.
I have created a class for parsing of json.
Here the code:
- (void)createJSONDictionaryFromURL:(NSURL *)url
{
NSURLRequest *request = [NSURLRequest requestWithURL:url];
(void)[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
jsonData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[jsonData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Fail with error");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSLog(#"%#", self.jsonDictionary);
}
In the Method connectionDidFinishLoading, is everything correct, the console shows the correct data.
But I want to use this in the viewDidLoad Method from my ViewController.
JSONParser *parser = [[JSONParser alloc] init];
NSDictionary *dict = [[NSDictionary alloc] init];
[parser createJSONDictionaryFromURL:url];
dict = parser.jsonDictionary;
NSLog(#"%#", dict);
The console shows (null), can anybody help me?
Sorry for my bad english
Your JSONParser is asynchronous because of the network connection (it is asynchronous). So, when you currently call parser.jsonDictionary you see that the data isn't ready yet.
You don't want to try blocking until the data is available, rather you should setup a callback to get the data to your view controller when it's ready (so you can save it and update the UI).
That could be done by adding a delegate property to your JSONParser and having the view controller assign itself and implement some callback method. Or, using less code, the JSONParser can offer a block property that the view controller sets and which is called in connectionDidFinishLoading: (make sure the #property uses (copy, nonatomic)`).

Returning a string from an NSURLRequest

Is anybody able to help me get a string returned from an NSURLRequest on an iPhone app? I have to send some user credentials to a URL and it will return a customer ID number. That is what I need to be pulled in as a string, I am not used to doing working with servers or HTTP requests, so any help will be great. I have already read the Apple Docs about it and am a bit lost on this part.
This is a standard pattern async downloader:
In .h file:
NSMutableData *responseData;
And .m file:
-(void) execute {
NSString *urlString = #"http://www.google.com";
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[responseData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[responseData appendData:data];
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
[connection release];
NSString *data = [[[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] autorelease];
NSLog(#"%#", data);
[responseData release];
}
This will download Google and outprint the content.

How to send Asynchronous URL Request?

I would like to know how do I get a return value 1 or 0 only.... back from an URL request asynchronously.
currently I do it in this way:
NSString *UTCString = [NSString stringWithFormat:#"http://web.blah.net/question/CheckQuestions?utc=%0.f",[lastUTCDate timeIntervalSince1970]];
NSLog(#"UTC String %#",UTCString);
NSURL *updateDataURL = [NSURL URLWithString:UTCString];
NSString *checkValue = [NSString stringWithContentsOfURL:updateDataURL encoding:NSASCIIStringEncoding error:Nil];
NSLog(#"check Value %#",checkValue);
this works, however it is blocking my main thread till I got a reply back from the URL, how do I set it so it will do it in a another thread instead of the main thread ?
EDIT: ANSWER
I end upcalling my function with this, it works well :)
[self performSelectorInBackground:#selector(shouldCheckForUpdate) withObject:nil];
you can use NSURLConnection class
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
and handle its response and errors using its delegate methods.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
You can find implementation of NSURLConnection
Apple docs: Using NSURLConnection
How To Use iOS NSURLConnection By Example
Edit: Although NSURLConnection is provided by apple is more recommended way of placing URL request. But I found AFNetworking library very time saving, easy to implement and robust yet simple as third party implementation. You should give it a try.
try this :
.h:
NSMutableData *responseData;
.m:
- (void)load
{
NSURL *myURL = [NSURL URLWithString:#"http://www.example.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[responseData release];
[connection release];
[textView setString:#"Unable to fetch data"];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[responseData
length]);
NSString *txt = [[[NSString alloc] initWithData:responseData encoding: NSASCIIStringEncoding] autorelease];
}
Use NSURLConnection and make your request.
Then you may start synchronous or asynchronous connection with NSURLConnection's methods :
Loading Data Synchronously
+ sendSynchronousRequest:returningResponse:error:
Loading Data Asynchronously
+ connectionWithRequest:delegate:
– initWithRequest:delegate:
– initWithRequest:delegate:startImmediately:
– start
Check the NSURLConnection class in Apple Developer API Reference.
Shamelessly copy from https://gist.github.com/knmshk/3027474. All credits go to https://gist.github.com/knmshk.
xmlData = [[NSMutableData alloc] init];
NSURL *url = [NSURL URLWithString:
#"http://forrums.bignerdranch.com/smartfeed.php?"
#"limit=NO_LIMIT&count_limit20&sort_by=standard&"
#"feed_type=RSS2.0&feed_style=COMPACT"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if (error) {
xmlData = nil;
NSLog(#"error:%#", error.localizedDescription);
}
[xmlData appendData:data];
}];
There is an example in the iOS XCode documentation called LazyTableImages. This does an asynchronous URL as well as asynchronous image load into UITableView cells displayed on the screen after scrolling stops. Excellent example of protocols, asynchronous data handling, etc.

purpose of using NSURLConnection while calling xml web-service ..?

why we are using NSURLConnection object in xml parsing ie.
for eg:
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
and then NSURLConnection delegate methods invoked
like:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
[connection release];
[receivedData release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
if(ObjNSXMLParser!=nil && [ObjNSXMLParser retainCount]>0){
[ObjNSXMLParser release];
ObjNSXMLParser = nil;
}
ObjNSXMLParser = [[NSXMLParser alloc]initWithData:receivedData];
ObjNSXMLParser.delegate=self;
[ObjNSXMLParser parse];
}
===============================
But we also get data directly by using: no need to initialize NSURLConnection object:
NSData *dt = [NSData DatawithcontentsofURL:urlname];
which approach is best ?and why ?
[NSDATA dataWithContentsOfURL:urlname] will block your application while it gets the data.
NSURL will let you get the data in the background so your UI can still work.
If you don't mind blocking the thread you're on, dataWithContentsOfURL is much easier to use. However, if you do that on the main thread you will really annoy the user if the loading takes a long time. They'll think the app has broken!

Get URL File Size before parsing

Me again! I am using NSURL to get a file then parse it. I have been looking for a couple of hours now on a progressbar i am trying to implement in my app. I know I first need to get the file size, then keep updating how much data i've downloaded as I continue to pull. I have seen the example using "ASIHTTPRequest" but is there a way to do it with what I already have?
Here is where I start the download.
-(void)parseNewData {
//start network activity spinner and release controller when done
parserDone = NO;
[root downloadIcon];
//create pool to avoid memory leak
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// get the XML path and start parsing
NSURL *pathURL = [NSURL URLWithString:#"http://www.mysite.com/myfile.xml"];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:pathURL];
[parser setDelegate:self];
[parser parse];
//drain pool
[pool drain];
[pool release];
}
Can someone point me in the right direction on how to get file size, then how to update how much I've downloaded. Thanks in advance!
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
CGFloat size = [[NSString stringWithFormat:#"%lli",[response expectedContentLength]] floatValue];
NSLog(#"Size : %f",size);
}
Above code will give you total size
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
totalDownloadedData += [data length]; // global integer
NSLog(#"Status : %d/%f",totalDownloadedData,size);
}
Above code will show you current status of downloading
You need to use NSURLConnection if you want to get the file size and the progress. You get delegate methods which you can use to monitor progress. The didSendBodyData: delegate method tells you how much data there is in bytes. The connectionDidFinishLoading is where you uget receivedData to use in your NSXMLParser code.
NSURLRequest *theRequest = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
receivedData = [[NSMutableData data] retain];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
// release the connection, and the data object
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
[connection release];
// receivedData is declared as a method instance elsewhere
[receivedData release];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite{
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{