how to stop nsurlconnection? - xcode

i'm using the url connection with nsfile handle to receive the data from server,
this is the code that i use,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response {
filename = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"Ep1.mp4";
[[NSFileManager defaultManager] createFileAtPath:filename contents:nil attributes:nil];
file =[NSFileHandle fileHandleForUpdatingAtPath:filename] ;
if (file) {
[file seekToEndOfFile];
}}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (file) {
[file seekToEndOfFile];
} [file writeData:data]; }
- (void)connectionDidFinishLoading:(NSURLConnection*)connection {
[file closeFile];
}
-(void)downloadFile{
targetURL = [NSURL URLWithString:#"http://some url "];
DownloadRequest = [NSURLRequest requestWithURL:targetURL cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:50.0];
DownloadConnection = [[NSURLConnection alloc] initWithRequest:DownloadRequest delegate:self];
if (DownloadConnection) {
receivedData = [NSMutableData data];
}
}
i want to stop the connection, when downloading file, so, i create the button
--->
- (void)buttonPressed:(id)sender
{
DownloadConnection = [[NSURLConnection alloc] initWithRequest: DownloadRequest delegate:self];
[ DownloadConnection cancel];
}
but doesn't work, the data still receiving, did i miss understand something?
or what can i do?

Edited :
this is the solution that i found:
- (void)buttonPressed:(id)sender
{
DownloadConnection = [[NSURLConnection alloc] initWithRequest: DownloadRequest delegate:self];
[ self.DownloadConnection cancel];
}
add the self to cancel the current connection...

Related

Replace NSUrlConnection with NSUrlSession

Hi I have a project using NSurlConnection I just want to replace it with NSUrlSession .Following is the code .KIndly help with the changes.
- (IBAction)getResponse:(id)sender
{
[status setText:#"Retrieving response async"];
[response setText:#""];
NSURL *requestUrl = [[NSURL alloc] initWithString:url.text];
NSURLRequest *request = [NSURLRequest requestWithURL:requestUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void)connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"Response recieved");
}
- (void)connection:(NSURLConnection*) connection didReceiveData:(NSData *)data
{
NSLog(#"Data recieved");
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[response setText:responseString];
[status setText:#"Response retrieved async"];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
}
Try this
[[[NSURLSession sharedSession]dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data, NSURLResponse *
_Nullable response, NSError * _Nullable connectionError) {
//Handle your response
}] resume];

how to load PHLivePhoto from server url?

NSURL *url = [NSURL URLWithString:#"http://192.168.1.50/download/1.jpg"];
//NSURL *url = [NSURL URLWithString:#"http://192.168.1.50/download/3.mov"];
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
// NSLog(#"%#",[res allHeaderFields]);
self.receiveData = [NSMutableData data];
self.sumLength=response.expectedContentLength;
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.receiveData appendData:data];
self.currentLength+=data.length;
double progress=(double)self.currentLength/self.sumLength;
self.progress.progress=progress;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
NSString *ourDocumentPath =[documentPaths objectAtIndex:0];
NSString *fileName=[ourDocumentPath stringByAppendingPathComponent:#"1.mov"];
if ([self.receiveData writeToURL:[NSURL fileURLWithPath:fileName] atomically:YES])
{
NSLog(#"OK Sucess");
}else
{
NSLog(#"No Fail");
}
}
I use this method download both jpg and mov to document dir. but is not work to play and use [PHAssetResourceManager defaultManager] writeDataForAssetResource from photolibary to save same dir and load ok.
2016-03-07 19:22:28.854 TestJiri[8641:5589436] /var/mobile/Containers/Data/Application/D100284B-74B2-41E1-B643-7B3EF71F99DE/Documents/1.jpg
2016-03-07 19:22:28.854 TestJiri[8641:5589436] /var/mobile/Containers/Data/Application/D100284B-74B2-41E1-B643-7B3EF71F99DE/Documents/1.mov
2016-03-07 19:22:28.899 TestJiri[8641:5597595] Error: Invalid video metadata
how to load them? thanks.

didReceiveData only getting called once on resuming download

I have a problem which I could really do with some help with please
I am using NSURLconnection to download a large file (27MB). the code work fine when there is no network interruption. In order to allow for network issues and only partially downloaded file I have added code to check to see how much of the file is downloaded and then using a server request to download the missing portion.
The code works as it should IF I download part of file, stop the program running and then run again - the download then commences where it left off and i have complete file.
However if I hit the download button a second time without stopping the program then didReceiveData only gets called once and adds just 200KB to the file and it tells me file has been succesfully downloaded.
Help please - I have spent ages trying to figure out what I'm doing wrong.
Code below:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"Response code = %d",httpResponse.statusCode );
file = [NSFileHandle fileHandleForUpdatingAtPath:filename] ;// file is in .h
if (file) {
[file seekToEndOfFile];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if (file) {
[file seekToEndOfFile];
NSLog(#"file is %#",file);
}
[self.file writeData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
if([[NSFileManager defaultManager] fileExistsAtPath:filename])
{
[file closeFile];
file = nil;
theConnection = nil;
filename = nil;
theRequest = nil;
}
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[file closeFile];
file = nil;
theConnection = nil;
filename = nil;
}
- (IBAction)downloadFile:(id)sender {
filename = [[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:movie1]; // filename is in .h file
theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:movieDownload1] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSUInteger downloadedBytes = 0;
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:filename]) {
NSError *error = nil;
NSDictionary *fileDictionary = [fm attributesOfItemAtPath:filename error:&error];
if (!error && fileDictionary)
downloadedBytes = [fileDictionary fileSize];
} else {
[fm createFileAtPath:filename contents:nil attributes:nil];
}
if (downloadedBytes > 0) {
NSString *requestRange = [NSString stringWithFormat:#"bytes=%d-",downloadedBytes];
[theRequest setValue:requestRange forHTTPHeaderField:#"Range"];
}
theConnection = nil;
theConnection = [NSURLConnection connectionWithRequest:theRequest delegate:self];
}
Instead of using seekToEndOfFile in didReceiveResponse and didReceiveData, you can try the following code snippet. It worked well for me.
- (id)initWithURL:(NSString *)downloadString
{
if (![super init])
return nil;
// Construct the URL to be downloaded
self.downloadURL = [[NSURL alloc]initWithString:downloadString];
self.downloadData = [[NSMutableData alloc] init];
self.downloadedFilename = [[self.downloadURL path] lastPathComponent];
[self downloadFile];
return self;
}
-(void) downloadFile
{
// set the filePath
docFolderPath = [NSHomeDirectory() stringByAppendingPathComponent: [NSString stringWithFormat: #"Documents/%#", self.downloadedFilename]];
self.downloadStream = [NSOutputStream outputStreamToFileAtPath:docFolderPath append:NO];
if (!self.downloadStream)
{
self.error = [NSError errorWithDomain:[NSBundle mainBundle].bundleIdentifier
code:-1
userInfo:#{#"message": #"Unable to create NSOutputStream", #"function" : #(__FUNCTION__), #"path" : self.downloadedFilename}];
return;
}
[self.downloadStream open];
self.downloadConnection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self];
[self.downloadConnection start];
}
//code snippet for the Resume functionality after your downloading gets paused/cancel
-(void) resumeInterruptedDownload
{
NSFileManager *fm = [NSFileManager defaultManager];
if ([fm fileExistsAtPath:docFolderPath])
{
NSError *error = nil;
NSDictionary *fileDictionary = [fm attributesOfItemAtPath:docFolderPath
error:&error];
if (!error && fileDictionary)
self.downloadedBytes = [fileDictionary fileSize];
} else
{
[fm createFileAtPath:docFolderPath contents:nil attributes:nil];
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
// Define the bytes we wish to download.
if(self.downloadedBytes != 0)
{
NSString *range = [NSString stringWithFormat:#"bytes=%i-", self.downloadedBytes];
[request setValue:range forHTTPHeaderField:#"Range"];
}
// Data should immediately start downloading after the connection is created.
self.downloadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:TRUE];
}
It worked perfectly for me in case of the large files in Mbs but for the small files in Kbs it sometimes fails. You don't have to try much in all these delegate methods of NSURLConnection. One thing you can do is that set the macros for each state i.e, cancel, pause, downloading,downloaded so that you can come to know that when do you want to resume the downloading. Also you can try the following http://nachbaur.com/blog/resuming-large-downloads-with-nsurlconnection.
I know it is too late to reply, but I just got into IOS. If you try this, please let me know whether it worked or not. Thanks :) :)

NSURLConnection asynchronous downloaded data saving to local file for iPhone?

i need to download a mp3 file from internet through my application and i found a solution , to use NSURLConnection and connection request. here is my code (code from another faq)
- (IBAction)downloadData:(id)sender
{
NSURL *myURL = [NSURL URLWithString:#"http://www.example.org/mp3song"];
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];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[responseData
length]);
NSString *txt = [[[NSString alloc] initWithData:responseData encoding: NSASCIIStringEncoding] autorelease];
}
how will i save this response data mp3 file to my local file of iPhone?
so i found the solution after a long googling which i forget to add the code
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *fileName = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myFile"];
[responseData writeToFile:fileName atomically:YES];
thankyou

NSURLConnection - Is it possible to wait/block on a request?

I need to wait for a response from a SOAP webservice, I am calling via a NSURLConnection as I need to manipulate the data being returned and then return it from my class to the calling class..
Here is my code:
#import <Foundation/Foundation.h>
#interface UsersBLL : NSObject {
NSMutableData *webData;
NSMutableString *soapResults;
NSXMLParser *xmlParser;
BOOL *recordResults;
NSNumber *EmailCount;
}
#property(nonatomic, retain) NSMutableData *webData;
#property(nonatomic, retain) NSMutableString *soapResults;
#property(nonatomic, retain) NSXMLParser *xmlParser;
-(int)checkEmailAddress:(NSString*)emailAddress;
#end
#import "UsersBLL.h"
#implementation UsersBLL
#synthesize webData;
#synthesize soapResults;
#synthesize xmlParser;
-(id)init {
self = [super init];
return self;
}
-(int)checkEmailAddress:(NSString*)emailAddress {
// Build the SOAP envelope
NSString *soapMessage = [NSString stringWithFormat:
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n"
"<CheckEmailAddress xmlns=\"http://tempuri.org/\">\n"
"<EmailAddress>%#</EmailAddress>\n"
"</CheckEmailAddress>\n"
"</soap:Body>\n"
"</soap:Envelope>\n", emailAddress];
NSLog(soapMessage);
NSURL *url = [NSURL URLWithString:#"http://photoswapper.mick-walker.co.uk/UsersService.asmx?op=CheckEmailAddress"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
[theRequest addValue: #"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue: #"http://tempuri.org/CheckEmailAddress" forHTTPHeaderField:#"SOAPAction"];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
else
{
NSLog(#"theConnection is NULL");
}
NSLog(#"%#", EmailCount);
}
-(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];
NSLog(theXML);
[theXML release];
if( xmlParser )
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
[connection release];
[webData release];
}
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *)qName
attributes: (NSDictionary *)attributeDict
{
if( [elementName isEqualToString:#"CheckEmailAddressResult"])
{
if(!soapResults)
{
soapResults = [[NSMutableString alloc] init];
}
recordResults = TRUE;
}
}
-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if( recordResults )
{
[soapResults appendString: string];
}
}
-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
if( [elementName isEqualToString:#"CheckEmailAddressResult"])
{
recordResults = FALSE;
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
EmailCount = [formatter numberFromString:soapResults];
[formatter release];
[soapResults release];
soapResults = nil;
}
}
#end
CheckEmailAddress is declared as returning an integer value (I know it returns nothing in the sample above).
What I ideally want, is through the CheckEmailAddress method, return the value retrieved from the web service. However as the call NSURLConnection does not wait until the request has completed, I cannot do it.
I would be grateful if anyone could give me any potential ideas for workarounds.
The simplest solution would be using [NSURLConnection sendSynchronousRequest:returningResponse:error:].
It does not allow as much control as the approach you've taken, but is usually enough for most applications.
I have just posted a solution which wraps an asynchronous NSURLConnection to be able to block the calling thread. In case you need more control than the standard [NSURLConnection sendSynchronousRequest:returningResponse:error:] you can check out this link on StackOverflow:
NSURLConnection blocking wrapper implemented with semaphores
You have two choices:
Use +[NSURLConnection sendSynchronousRequest:returningResponse:error:]
Schedule the connection in a custom runloop mode, and run the loop in that mode until the data arrives or you have need to cancel the connection
It all depends on the level of asynchronism you need:
If it's OK to stay blocked during the whole request you may want to use
+[NSURLConnection sendSynchronousRequest:returningResponse:error:]
But, as suggested by Wade, be careful to add a timeout to your NSURLRequest, otherwise the connection might blocks and your application will hang.
If not, you can simply use the NSNotificationCenter. But you must be careful with race conditions over your data, specially if you are handling multiple requests

Resources