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{
Related
I have an application and I used to get my json data with dataWithContentsOfURL.
But because I need to get it an asynchrone fashion.
Now that I use NSURLConnection to handle this I don't receive any useful data all I get is statuscode 200 in the didReceiveResponse method but didReceiveData is never called.
And at connectionDidFinishDownloading destinationURL returns null.
I have no idea wat couses this problem and I would really appreciate some help.
the delegate
#import "NetWorkToGuiDelegate.h"
#implementation NetWorkToGuiDelegate
#synthesize data;
#synthesize caller;
- (id) init: (SEL) pointer :(NSObject *) c;
{
doWhenDone = pointer;
self.caller = c;
data = [[NSMutableData alloc]init];
return self;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];
NSLog(#"%#",responseText);
}
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL
{
NSLog(#"post download finished");
data = [NSData dataWithContentsOfURL:destinationURL];
NSLog(#"data: %#",data);
NSLog(#"URLconnection %#", connection.currentRequest);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[caller performSelector:doWhenDone withObject:data];
#pragma clang diagnostic pop
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.data setLength:0];
NSHTTPURLResponse *resp= (NSHTTPURLResponsae *) response;
NSLog(#"got responce with status %d",[resp statusCode]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d
{
NSLog(#"data recieved %#",d);
[self.data appendData:d];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error", #"")
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK", #"")
otherButtonTitles:nil] show];
NSLog(#"failed");
}
// Handle basic authentication challenge if needed
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSString *username = #"username";
NSString *password = #"password";
NSURLCredential *credential = [NSURLCredential credentialWithUser:username
password:password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
#end
the call
NetWorkToGuiDelegate *nwgd = [[NetWorkToGuiDelegate alloc] init:#selector(login:) :self];
NSString *stringURL = [NSString stringWithFormat:#"%#%#%#%#", dk.baseURL, #"menu?code=",dk.loginCode,#"&v=1"];
NSURL *url = [NSURL URLWithString:stringURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:nwgd];
[urlConnection start];
I'll just add that the call happens on the main thread
Actually there is a lot of points to make the answer of this question and there are so many questions on SO itself
Go through this nice post
And a must Read doc from apple itself.(contains code samples and explanations)
Hope this will solve the problems for you.
EDIT
-(void)startAConnection
{
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData data];
} else {
// Inform the user that the connection failed.
}
}
- (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 didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
[receivedData appendData: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
{
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
}
Call startAConnection to start the process
NOTE: Don't forget <NSURLConnectionDelegate> in the .h
please help me on this how to start thread on background in iphone on every when application is start for
in my sqlite database table i have one column sync status .there i have 3 value 0,1,3.i have to call these values on database table.0 means if application has synced data to server.if any data in my database is updated the sync status changes to 1 and 3 means data is being send to server i.e syncing is in progress.
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [[NSMutableData data] retain];
} else {
// Inform the user that the connection failed.
}
Then implement delegate methods of NSURLConnection
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
if(!receivedData){
receivedData = [[NSMutableData alloc]init];
}
[receivedData appendData:data];
}
- (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]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// do something with the data
// receivedData is declared as a method instance elsewhere
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
// release the connection, and the data object
[connection release];
[receivedData release];
}
Hope this helps
You can use NSThread class method to start the new thread.e.g.
[NSThread detachNewThreadSelector:#selector(newThread) toTarget:self withObject:nil];
///////
-(void)newThread{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
///your code
[pool release];
}
for more read Thread Programming guide
starting threads in background easily done with NSInvocation, all you need to know is here
there is GCD but each to their own
Can any one of you post the code snippet, example tutorial on handling the multiple
NSURLConnections from the same viewController using cocoa Touch framework....
Thanks for all your future help.....
I handled multiple NSUrlConnections using a NSMutableDictionary which keeps track of which instance of NSMutableData a particular NSURLConnection should save its result to.
At the beginning of my class I define:
NSMutableDictionary *dataDictionary;
Then in my loadData method, I have:
// Create the request
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:currentCam]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:30];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
NSMutableData *receivedData = receivedData = [[NSMutableData alloc] init];
//keep track of this connection by adding it to subViewDictionary and dataDictionary with appropriate objects.
[dataDictionary setObject:receivedData forKey:[theConnection description]];
}
else {
NSLog(#"ERROR DOWNLOADING WITH NSURLCONNECTION");
}
[theConnection release];
I use [theConnection description] as my key and an instance of MSMutableData as the object in my dictionary, so later I can look up which instance goes with a particular connection. If you fail to do this you can have issues with data corruption (multiple connections can all save their data to the same variable).
Then, I define the following NSURlConnection delegate methods:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSMutableData *)data
{
//look up in dictionary to find out which recievedData instance to use.
NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
// Append the new data to receivedData.
[theReceivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//Lookup in the dictionary to find the correct instance of recievedData to put image into.
NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
[theReceivedData setLength:0];
[activityIndicator stopAnimating];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// inform the user that there was an error
NSLog(#"Connection failed! Error - localizedDescription:%# NSURLErrorFailingURLStringErrorKey:%#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
[theReceivedData release];
//remove keys for this connection since it did not load.
[dataDictionary removeObjectForKey:[connection description]];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//look up correct instance of recievedData in teh dictionary for this connection
NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
NSLog(#"Succeeded! Received %d bytes of data",[theReceivedData length]);
//---do stuff with data here//
[theReceivedData release];
}
There is a good tutorial on NSURlConnection here for a single connection. My code is based on that with the addition of the NSMutableDictionary to keep track of each NSUrlConnection and each NSMutableData instance.
I hope that makes sense and is helpful!
See this link for the answer. It wraps nsurlconnection with asihttp, which makes your life much easier.
Does ASIHTTP support multi threads?
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!
So here's my issue:
I followed the NSURLConnection tutorial in the iPhone Developer Documentation almost to the T, and it only kinda works.
Here's where it all goes wrong:
The object seems to be created correctly and delegates to connectionDidFinishLoading, but with any URL I try to load the response data always ends up only being 0 bytes. I am running in the simulator if that makes any difference.
Here's my relevant code:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"WVFS Player";
//create a request
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://wvfs.josh-kaplan.com/nowPlaying.php"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create a connection
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
// create the datum
responseData=[[NSMutableData data] retain];
} else {
// code this later
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[responseData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// make it work
NSLog(#"Succeeded! Received %d bytes of data:",[responseData length]);
// release it
[connection release];
[responseData release];
}
And here's my log output:
[Session started at 2010-03-14 09:01:09 -0400.]
2010-03-14 09:01:14.784 WVFS[19571:207] Succeeded! Received 0 bytes of data:
Any ideas?
You forgot to implement connection:didReceiveData:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}