I am trying to fill a UITableView by fetching an URL. To avoid freeze UI I using dispatch_async(dispatch_queue_t queue, ^(void)block) making asynchronous fetching.
In the asynchronous block using NSRunLoop to waiting response.
Here's my fetching code:
- (BOOL)isFinished {
return _finished;
}
- (void)startReceive {
NSURLRequest* request = [NSURLRequest requestWithURL:self.baseURL];
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
assert(self.connection);
}
- (void)stopReceiveWithStatus:(NSString*)statusCode {
if (self.connection) {
[self.connection cancel];
self.connection = nil;
}
self.finished = YES;
NSLog(#"Stop Receive with status code %#", statusCode);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
assert(connection == self.connection);
NSHTTPURLResponse* httpResponse = nil;
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
httpResponse = (NSHTTPURLResponse*) response;
if (httpResponse.statusCode != 409) {
// I need 409 to fetch some data
[self stopReceiveWithStatus:[NSString stringWithFormat:#"HTTP error %2d", httpResponse.statusCode]];
}
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
assert(connection == self.connection);
self.sessionID = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
assert(connection == self.connection);
[self stopReceiveWithStatus:#"Connection failed"];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
assert(connection == self.connection);
[self stopReceiveWithStatus:nil];
}
UITableViewController:
// refreshControl handler
- (IBAction)refresh {
[self startRefreshingAnimation];
dispatch_queue_t loaderQ = dispatch_queue_create("loading transmission data", NULL);
dispatch_async(loaderQ, ^{
[self foo];
while(!self.t.finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self endRefreshingAnimation]; // end
});
});
}
- (void)foo {
NSLog(#"session id: %#", self.t.sessionID);
}
That sessionID will be filled when HTTP request has done. Now the problem is I can not get the sessionID when first call because the first time it not be filled and second time it works good. How can I get it when first call?
I'm new to iOS. If you have a better solution to solve this problem please tell me, thanks.
There is a good framework, don't waste your time.
https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking
Upd.
You can do your request like:
NSURL *url = self.baseURL;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
height, #"user[height]",
weight, #"user[weight]",
nil];
[httpClient postPath:#"/myobject" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"Request Successful, response '%#'", responseStr);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"[HTTPClient Error]: %#", error.localizedDescription);
}];
You should use an third-party library to handle network connections, such as STHTTPRequest:
STHTTPRequest *r = [STHTTPRequest requestWithURLString:#"http://www.apple.com"];
r.completionBlock = ^(NSDictionary *headers, NSString *body) {
// ...
};
r.errorBlock = ^(NSError *error) {
// ...
};
[r startAsynchronous];
Related
I am using this custom class to download data from Server(ASP.NET IIS 7.5) using a certificate. It works just fine except that on every request the didReceiveChallenge method is called every time and credentials has to be applied again and again. The performance suffers greatly.
How can we avoid this?
Thanks.
#import "ServerRequest.h"
#import <UIKit/UIKit.h>
#implementation ServerRequest{
NSMutableData * recievedData;
NSString * operationName;
NSString * operationParameters;
DataOperationType operationType;
NSURL* downloadURL;
NSData * HTTPBodyData;
UIView * waitView;
UIProgressView * progressView;
}
- (instancetype)init{
if(self = [super init]) {
}
return self;
}
- (NSURLSession *)normalSession{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLProtectionSpace * protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[Config getBaseURL] port:443 protocol:#"https" realm:nil authenticationMethod:NSURLAuthenticationMethodClientCertificate];
[configuration.URLCredentialStorage setDefaultCredential:[Helper getCredential] forProtectionSpace:protectionSpace];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
return session;
}
- (instancetype)initWithRequest:(NSString *)request
{
if(self = [super init]) {
operationType = DataOperationTypeData;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request Dicionary:(NSString *) dataDictionary{
if(self = [super init]) {
operationType = DataOperationTypeHTMLFrom;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
operationParameters = dataDictionary;
}
return self;
}
- (instancetype)initWithRequest:(NSString *)request data:(NSData *) bodyData{
if(self = [super init]) {
operationType = DataOperationTypeBodyData;
downloadURL = [NSURL URLWithString:request];
NSLog(#"Created download operation for URL: %#", [downloadURL absoluteString]);
HTTPBodyData = bodyData;
}
return self;
}
- (void) performOperationWithCompletion:(ServerRequestCompletion)onCompletion error:(ServerRequestError)onError{
if (self.showProgressView){
[self configureProgressView];
}
if (self.parentView) {
waitView = [Config createWaitView:self.parentView];
}
self.completion = onCompletion;
self.error = onError;
NSMutableURLRequest *request;
request = [NSMutableURLRequest requestWithURL:downloadURL];
[request setHTTPMethod:#"POST"];
[request setValue:#"utf-8" forHTTPHeaderField:#"Accept-Charset"];
if (operationType == DataOperationTypeHTMLFrom) {
NSData *postData = [operationParameters dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"utf-8" forHTTPHeaderField:#"Accept-Charset"];
[request setValue:[NSString stringWithFormat:#"%ld", (unsigned long)postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
}
else if (operationType == DataOperationTypeBodyData) {
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%ld", (unsigned long)HTTPBodyData.length] forHTTPHeaderField:#"Content-Length"];
[request addValue: #"multipart/form-data; charset=utf-8" forHTTPHeaderField: #"Content-Type"];
[request setHTTPBody:HTTPBodyData];
}
else{
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
}
NSURLSession * defaultSession = [self normalSession];
NSURLSessionTask * dataTask = [defaultSession dataTaskWithRequest:request];
if (!dataTask) {
self.error([EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:-1 userInfo:#{NSLocalizedDescriptionKey: #"Could not initialize connection"}]);
}else{
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setHidden:NO];
// [appDelegate.progressView setProgress:0];
});
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[dataTask resume];
}
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler{
//NSURLProtectionSpace *protectionSpace = [challenge protectionSpace];
NSURLCredential *credential = [Helper getCredential];
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodNTLM])
{
if (challenge.previousFailureCount >= 3)
{
// handle the fact that the previous attempt failed
EXError* error = [EXError errorWithDomain:NSURLErrorDomain code:403 userInfo: #{NSLocalizedDescriptionKey: #"Unable to verify account information."}];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
self.error(error);
}else{
NSURLCredentialPersistence persistence = NSURLCredentialPersistenceForSession;
NSString * userName = [Config getUserName];
NSString * password = [Config getPassword];
NSURLCredential *loginCredential = [NSURLCredential credentialWithUser:userName password:password persistence:persistence];
completionHandler(NSURLSessionAuthChallengeUseCredential, loginCredential);
[self removeWaitView];
}
}
else if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
//completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate)
{ NSLog(#"\n______________________________________________________ Authentication Method Client Certificate _________________________________________________");
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
[self removeWaitView];
}
else{
completionHandler(NSURLSessionAuthChallengeRejectProtectionSpace, nil);
[self removeWaitView];
}
}
-(void) configureProgressView{
UIViewController * topController = [Helper currentTopViewController];
if (![topController isKindOfClass:[UINavigationController class]]) {
return;
}
UINavigationController * navigationController = (UINavigationController *)topController;
UINavigationBar * navigationBar = [navigationController navigationBar];
progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressView.frame = CGRectMake(navigationBar.frame.origin.x, navigationBar.frame.size.height - 5, navigationBar.frame.size.width, 5);
[navigationBar addSubview:progressView];
}
-(void) removeWaitView{
[waitView removeFromSuperview];
waitView = nil;
}
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error{
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
NSDictionary *responseHeaders = ((NSHTTPURLResponse *)response).allHeaderFields;
NSLog(#"headers: %#", responseHeaders.description);
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode >= 400) { // Client/Server Error
EXError * error = [EXError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:httpResponse.statusCode userInfo:#{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]}];
self.error(error);
NSLog(#"Failed with Error %ld : %#", (long)httpResponse.statusCode, [NSHTTPURLResponse localizedStringForStatusCode:httpResponse.statusCode]);
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
return;
}
}
completionHandler(NSURLSessionResponseAllow);
[self removeWaitView];
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
if (!recievedData) {
recievedData = [NSMutableData new];
}
[recievedData appendData:data];
if ([dataTask countOfBytesExpectedToReceive] !=NSURLSessionTransferSizeUnknown) {
double progress = (double)[dataTask countOfBytesReceived] / (double) [dataTask countOfBytesExpectedToReceive];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setProgress:progress animated:YES];
});
}
}
// DLog(#"progress : %lld", [dataTask countOfBytesExpectedToReceive]);
}
//- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
// didSendBodyData:(int64_t)bytesSent
// totalBytesSent:(int64_t)totalBytesSent
// totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
// // DLog(#"Did Sent %f", (double)totalBytesSent);
//
// if (self.showProgressView) {
//
// dispatch_async(dispatch_get_main_queue(), ^{
//
// AppDelegate_Shared * appDelegate = (AppDelegate_Shared *)([UIApplication sharedApplication]).delegate;
// [appDelegate.progressView setProgress:
// (double)totalBytesSent /
// (double)totalBytesExpectedToSend animated:YES];
//
// });
// }
//}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (self.showProgressView) {
dispatch_async(dispatch_get_main_queue(), ^{
[progressView setHidden:YES];
});
}
// NSString *myString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// NSLog(#"%#", myString);
if(error == nil)
{
// SBJSON *json = [SBJSON new];
// NSString *responseString = [[NSString alloc] initWithData:recievedData encoding:NSUTF8StringEncoding];
//
// //NSLog(#"Finished (%#) %d bytes. %#", [downloadURL absoluteString], [data length], responseString);
//
// NSDictionary *dataSet = [json objectWithString:responseString];
NSDictionary* dataSet = [NSJSONSerialization
JSONObjectWithData:recievedData
options:kNilOptions
error:&error];
self.completion(dataSet);
}
else{
// if (error.code == -999) {
// return;
// }
// NSString * httpBody = [[NSString alloc] initWithData:task.currentRequest.HTTPBody encoding:NSUTF8StringEncoding];
//
// httpBody = [NSString stringWithFormat:#"%s\n%#", __PRETTY_FUNCTION__, httpBody];
// [Helper MsgBox:httpBody];
EXError * exError = [EXError errorWithDomain:error.domain code:error.code userInfo:#{NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode:error.code]}];
self.error(exError);
// DLog(#"Error %#", [error localizedDescription]);
}
}
#end
One of the reasons can be a check of HTTPS the certificate.
Apple Documentation
This instance contains a protectionSpace property whose authenticationMethod property indicates the kind of challenge being issued (such as a request for a username and password, or a client certificate). You use this value to determine whether you can handle the challenge.
Adding this precondition can check the authentication method and call the handler.
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
return;
}
You can find authentication methods constants here
My application having around 10 to 30 webservices(both get/post).previously i have used Async NSURLconnection. which takes around 5 sec to excute all services. But now i have replaced NSurlsession which get delay in response compare to nsurlconnection ,it is delayed by 4 to 6 times . here i have attached one of the webservice method code for reference . like below i have code for all methods .
Example NSURLsession code
#pragma mark - NSURLSession
- (NSURLSession *)createSession
{
NSLog(#"DSCReturnAPI: %s",__func__);
static NSURLSession *session = nil;
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = WEBSERVICE_TIMEOUT;
session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
return session;
}
#pragma mark - API Callbacks
-(void)getMyData{
#try {
_webServieRequestType = HWDSCReturnGetRequestType;
NSString *countrycode = [BusinessManager sharedInstance].countryCode;//[HWUserDefaults countryCode];
NSString *userid = [BusinessManager sharedInstance].userId;// [HWUserDefaults userId];
NSString *accessToken = [BusinessManager sharedInstance].accessToken;//[HWUserDefaults accessToken];
NSString *deviceId = [HWUserDefaults deviceId];
[HelperCallbacks logText:[NSString stringWithFormat:#"AccessToken %#",accessToken]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:API_DSCRETURN(countrycode,userid)]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:accessToken forHTTPHeaderField:#"Authorization"];
[request setValue:deviceId forHTTPHeaderField:#"deviceId"];
[request setValue:#"ba598025146eff37e26c9150b180a78b" forHTTPHeaderField:#"If-None-Match"];
theSession = [self createSession];
theDataTask = [theSession dataTaskWithRequest:request];
[theDataTask resume];
}
#catch (NSException *exception) {
[ExceptionHandler sendException:exception];
}
}
#pragma mark - NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
NSLog(#"DSCReturnAPI: %s",__func__);
// NSArray *dataArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if (theSession == session) {
if (_receivedData == nil) {
_receivedData = [[NSMutableData alloc] initWithData:data];
} else {
[_receivedData appendData:data];
}
}
else
{
//NSLog(#"");
}
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
NSLog(#"DSCReturnAPI: %s",__func__);
if (theSession == session) {
[BusinessManager sharedInstance].urlResponseRecieved = NO;
NSLog(#"DSCReturnAPI: httpResponse:%#",response);
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
httpStatusCode =(int) [httpResponse statusCode]; // To track response Code:
NSLog(#"DSCReturnAPI : Http code:%d",httpStatusCode);
NSLog(#"DSCReturnAPI : Headers %#",[httpResponse allHeaderFields]);
_receivedData = [[NSMutableData alloc]init]; }
completionHandler(NSURLSessionResponseAllow);
}
#pragma mark - NSURLSessionTaskDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
NSLog(#"DSCReturnAPI: %s",__func__);
NSLog(#"DSCReturnAPI: didFailWithError :error : %# errorCode: %ld",error.description,(long)error.code);
#try {
if ([self.serviceDelegate conformsToProtocol:#protocol(ServiceMgrProtocol)] && [self.serviceDelegate respondsToSelector:#selector(webServiceDidFailDSCReturnWithError:)]&& error.code != 0) {
[self.serviceDelegate webServiceDidFailDSCReturnWithError:error.localizedDescription];
}
else {
NSLog(#"DSCReturnAPI:SUCCESS");
[self processResponse];
}
}
#catch (NSException *exception) {
[ExceptionHandler sendException:exception];
}
#finally {
if (theSession) {
theSession = nil;
}
_receivedData = nil;
} }
I think no need to go for such methods of NSURLSession . It has its own block which runs on main thread.
NSMutableURLRequest *request =[[NSMutableURLRequest alloc] initWithURL:requestURL];
NSLog(#"fetchAPromotionWithType = %#", requestURL);
[request setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int responseStatusCode = (int)[httpResponse statusCode];
if ( responseStatusCode == OK_RESPONSE_CODE || responseStatusCode == CREATED_RESPONSE_CODE || responseStatusCode == ACCEPTED_RESPONSE_CODE || responseStatusCode == PARTIAL_RESPONSE_CODE)
{
if (data)
{
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"Data->%#",dict);
if (dict != nil && [dict isKindOfClass:[NSDictionary class]])
{
NSDictionary *dataDict = [dict objectForKey:#"data"];
if (dataDict != nil && [dataDict isKindOfClass:[NSDictionary class]])
{
//Get your success Data
}
}
}
}
else
{
if (responseStatusCode == 0)
{
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:#"No Connection! Please try again.", #"message", nil];
//Get Your Fail Data
}
else if (data)
{
// NSArray *tempArray = #[#"fan", #"vungle"];
//[JLSharedData sharedManager].savedWaterfallInterstitialArray = nil; //testing
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Get Your Fail Data
}
}
});
}];
[task resume];
}];
I've read lots of posts regarding this problem but I couldn't get the callback delegate to work...
I've read that delegate cannot be in a background Thread or it won't get called. I think that this may be the issue... but... well let me put some code here to explain better my problem and see what you guys think.
in main thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#try {
ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init];
[assetLibrary assetForURL:[object valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset)
{
ALAssetRepresentation *rep = [asset defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];//this is NSData may be what you want
//[data writeToFile:photoFile atomically:YES];//you can save image later
UIImage *image = [UIImage imageWithData:data];
CGFloat compression = 0.9f;
CGFloat maxCompression = 0.5f;
int maxFileSize = 1280*720; //ou usar 40960 = 40MB ?
NSData *imageData = UIImageJPEGRepresentation(image, compression);
while ([imageData length] > maxFileSize && compression > maxCompression)
{
compression -= 0.1;
imageData = UIImageJPEGRepresentation(image, compression);
}
NSString *guid = [self.idMediasAvailable lastObject];
//NSString *guid = [[NSUUID UUID] UUIDString];
NSString *boundary = #"-endUploadBoundary-";
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",boundary];
[client addBlobToContainer:[container objectAtIndex:self.mycontainerIndex] blobName:[NSString stringWithFormat:#"%#.jpg", guid] contentData:imageData contentType:contentType ];
[uploadedMediaID setObject:object forKey:guid];
[confirmMedias addObject:guid];
[listUploadedMedias addObject:object];
[self.idMediasAvailable removeLastObject];
// [allUploadedLock lock];
// [allUploadedLock unlockWithCondition:0];
}
failureBlock:^(NSError *err) {
NSLog(#"Error: %#",[err localizedDescription]);
[allUploadedLock lock];
[allUploadedLock unlockWithCondition:0];
}];
}
#catch (NSException *exception) {
NSLog(#"Error uploadMedia: %#",[object valueForKey:UIImagePickerControllerReferenceURL]);
}
});
[allUploadedLock lockWhenCondition:0];
[allUploadedLock unlock];
this is the addToBlobContainer selector:
- (void)addBlobToContainer:(BlobContainer *)container blobName:(NSString *)blobName contentData:(NSData *)contentData contentType:(NSString*)contentType withBlock:(void (^)(NSError*))block
{
CloudURLRequest* request = nil;
if(_credential.usesProxy)
{
request = [_credential authenticatedRequestWithEndpoint:#"/SharedAccessSignatureService/blob" forStorageType:#"blob" httpMethod:#"PUT" contentData:contentData contentType:contentType, #"x-ms-blob-type", #"BlockBlob", nil];
}
else
{
NSString* containerName = [container.name lowercaseString];
NSString* endpoint = [NSString stringWithFormat:#"/%#/%#", [containerName URLEncode], [blobName URLEncode]];
request = [_credential authenticatedRequestWithEndpoint:endpoint forStorageType:#"blob" httpMethod:#"PUT" contentData:contentData contentType:contentType, #"x-ms-blob-type", #"BlockBlob", nil];
}
[request fetchNoResponseWithBlock:^(NSError* error)
{
if(error)
{
if(block)
{
block(error);
}
else if([(NSObject*)_delegate respondsToSelector:#selector(storageClient:didFailRequest:withError:)])
{
[_delegate storageClient:self didFailRequest:request withError:error];
}
return;
}
if(block)
{
block(nil);
}
else if([(NSObject*)_delegate respondsToSelector:#selector(storageClient:didAddBlobToContainer:blobName:)])
{
[_delegate storageClient:self didAddBlobToContainer:container blobName:blobName];
}
}];
}
no breakpoint is hit inside the block [request fetchNoResponseWithBlock:ˆ(NSError *error) ...];
and this is the fetchNoResponseWithBlock:ˆ selector:
- (void) fetchNoResponseWithBlock:(noResponseBlock)block {
_noResponseBlock = [block copy];
[NSURLConnection connectionWithRequest:self delegate:self];
}
and in this same file I have the delegate selectors
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
and none of these are hit as well... btw the interface declaration is #interface CloudURLRequest : NSMutableURLRequest
Ok now the strange thing is that the breakpoints inside the delegate selectors
are hit when the page is opened and another request is made to get the Blob Containers... but when I try to send a file the file is sent and there is no callback! (I manually check the blob and it uploaded successfully)
I think that when I do this:
[assetLibrary assetForURL:[object valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) {
is this block running on a background thread by any chance? or Any suggestions?
I do need the callback to work because I have to unlock a NSLock only when the file completes the upload.
Thanks a lot in advance!
Our requirements include checking Internet access to a specific file on the web-server. This file is checked every n minutes. NSURLRequests never calls connection:didFailWithError whether or not there is an internet connection. And the HTTP status is always 200. Apple's reachibility only works for domains, not files- so it doesn't meet the requirements. How can I reliably discover if I can reach this file every n minutes? Why isn't the http status code really the http status code?
Other stackoverflow questions that would seem to answer this question do not work:
1. How could connectionDidFinishLoading: run if no file is found on server?
2. Testing use of NSURLConnection with HTTP response error statuses
I tried using another queue with a completion block, but that also didn't work.
-(void) updateConnectionStatus
{
NSURL *url = [NSURL URLWithString:(NSString*)[appValues getValueForSettingsKey:#"company.project.test.pingURL"]];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
//NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//__block __typeof__(self) _self = self;
connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
/*
[NSURLConnection
sendAsynchronousRequest:urlRequest queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
int code = [httpResponse statusCode]; // ALWAYS 200 no matter what
NSString *pingFile = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",error); // NEVER has an error
//This doesn't even work because it remembers FOREVER the value once it gets it.
if ([#"Ping!" isEqualToString:pingFile])
{
dispatch_async(dispatch_get_main_queue(), ^{
[_self companyConnection:YES];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[_self companyConnection:NO];
});
}
}];
*/
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR: %#", error); // Never get here
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *aResponse = (NSHTTPURLResponse*)response;
NSLog(#"received a response: %ld",(long)[aResponse statusCode] );
if ([response respondsToSelector:#selector(statusCode)])
{
int statusCode = [((NSHTTPURLResponse *)response) statusCode];
// statusCode is always 200
if (statusCode >= 400)
{
[companyConnection cancel]; // stop connecting; no more delegate messages
NSDictionary *errorInfo
= [NSDictionary dictionaryWithObject:[NSString stringWithFormat:
NSLocalizedString(#"Server returned status code %d",#""),
statusCode]
forKey:NSLocalizedDescriptionKey];
}
}
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(#"received data");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Finished");
}
Try with setting cachePolicy as NSURLRequestReloadIgnoringCacheData while constructing the NSURLRequest object
Thanks to Wain and Rob for putting me onto the right path. One way to keep the cache clear is adding this method to your NSURLConnectionDelegate:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
I am trying to execute a async http request. but the call back log is not working. please analyze the code and suggest me the cause of this issue. I have seen the class examples in many places. But here i am calling it from a main function.
#interface HTTP : NSObject
#property (nonatomic,retain) NSMutableData *receivedData;
- (void) get : (NSString *) urlString;
#end
#implementation HTTP
#synthesize receivedData;
- (void)get: (NSString *)urlString {
NSLog ( #"GET: %#", urlString );
self.receivedData = [[NSMutableData alloc] init];
NSURLRequest *request = [[NSURLRequest alloc]
initWithURL: [NSURL URLWithString:urlString]
cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: 10
];
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request
delegate:self
startImmediately:YES];
[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];
[receivedData appendData:responseString];
}
#end
int main(const int c , char *arg[]){
HTTP *http = [[HTTP alloc] init];
[http get:#"http://www.apple.com"];
return 0;
}
Your program does not have a "run loop", therefore it terminates immediately after
[http get:#"http://www.apple.com"];
has returned, before any delegate functions are called. (Note that NSURLConnection works asynchronously.)
If this is for a stand-alone OS X application, you could to the following:
int main(const int c , char *arg[]){
HTTP *http = [[HTTP alloc] init];
[http get:#"http://www.apple.com"];
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
return 0;
}
where shouldKeepRunning is a (global) Boolean variable that is initially YES, and set to NO in
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
shouldKeepRunning = NO;
}
and also in connection:didFailWithError:. Or you add a Boolean property loading to your HTTP class.
If this is for an iOS application or a OS X Cocoa application, then you already have a run loop and don't have to add your own.
/*
Till the application finishes loading, the main thread is kept alive so that the delegate methods are called.
Hence the while loop below.
*/
while(!finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
Here is my working code.
#implementation HTTP
#synthesize receivedData,retStr,delegate;
- init {
if ((self = [super init])) {
receivedData = [[NSMutableData alloc] init];
}
return self;
}
- (void)get: (NSString *)urlString {
NSLog ( #"GET: %#", urlString );
self.receivedData = [[NSMutableData alloc] init];
NSURLRequest *request = [[NSURLRequest alloc]
initWithURL: [NSURL URLWithString:urlString]
cachePolicy: NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval: 10
];
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request
delegate:self
startImmediately:YES];
while(!finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
if(!connection) {
NSLog(#"connection failed :(");
} else {
NSLog(#"connection succeeded :)");
}
}
- (void)post:(NSString*)urlString: (NSString*)body: (NSObject*) sender {
// POST
NSMutableString* requestURL = [[NSMutableString alloc] init];
[requestURL appendString:urlString];
NSMutableString* requestBody = [[NSMutableString alloc] initWithString:body];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: [NSString stringWithString:requestURL]]];
NSString* requestBodyString = [NSString stringWithString:requestBody];
NSData *requestData = [NSData dataWithBytes: [requestBodyString UTF8String] length: [requestBodyString length]];
[request setHTTPMethod: #"POST"];
[request setValue:#"text/html; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: requestData];
NSURLConnection *postConn= [[NSURLConnection alloc] initWithRequest:request delegate:sender];
/*
Till the application finishes loading, the main thread is kept alive so that the delegate methods are called.
Hence the while loop below.
*/
while(!finished) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
if(!postConn) {
NSLog(#"POST connection failed :(");
} else {
NSLog(#"POST connection succeeded :)");
}
}
// ====================
// Callbacks
// ====================
#pragma mark NSURLConnection delegate methods
- (NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)redirectResponse {
NSLog(#"Connection received data, retain count");
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Received response: %#", response);
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"Received %lu bytes of data", [data length]);
[receivedData appendData:data];
NSLog(#"Received data is now %lu bytes", [receivedData length]);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSRunAlertPanel(#"Error",[NSString stringWithFormat:#"Could not connect to server.Following error occured:\n\n%#", error], nil, nil, nil);
NSLog(#"Error receiving response: %#", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Once this method is invoked, "responseData" contains the complete result
NSLog(#"Succeeded! Received %lu bytes of data", [receivedData length]);
NSString *dataStr=[[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding] ;
retStr = [NSString stringWithString:dataStr];
finished =TRUE;
// [self returnDcString:dataStr];
// NSLog(#"%#",dataStr);
if ([delegate respondsToSelector:#selector(didFinishDownload:)]) {
NSLog(#"Calling the delegate");
//NSString* dataAsString = [[[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding] autorelease];
// [delegate performSelector:#selector(didFinishDownload:) withObject: dataStr];
}
}
- (void)setDelegate:(id)val
{
delegate = val;
}
- (id)delegate
{
return delegate;
}
#end