How to check a timeout occurred in ios url connection? - ios

I have used URLRequest to fetch a html file from a pc in my wifi network.
My app fetches a html file from my fileserver and the filename is a number which is typed in the app. Also I have given a 20 seconds timeout for the request. How can I detect whether timeout occurred because I have 2 situations,
1. file does not exist
2. connection is slow
In urlrequest, there is a BOOL for error,no description.
Suggest me a method if possible.
My code is below for only urlrequest
-(void)getHtmlContent{
[self.spinner startAnimating];
NSString *str = #"http://192.168.1.250/rec/";
// NSString *str = #"file:///Volumes/xampp/htdocs/";
str = [str stringByAppendingString:numEntered.text];
str = [str stringByAppendingString:#".html"];
NSURL *url=[NSURL URLWithString:str];
//self.htmlContent = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//NSURLRequest *request = [NSURLRequest requestWithURL:url];
request.timeoutInterval = 20.0;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *localfile, NSURLResponse *response, NSError *error) {
if(!error){
if([request.URL isEqual:url]){
NSString *content = [NSString stringWithContentsOfURL:localfile encoding: NSUTF8StringEncoding error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[numEntered setText:#"0"];
text = #"";
[self.spinner stopAnimating];
self.htmlContent = content;
NSString *myHTMLString = self.htmlContent;
if(myHTMLString != nil) {
if([myHTMLString isEqualToString:#"3"]){
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle:#"LogIn Success" message:#"" delegate:self cancelButtonTitle:#"Continue" otherButtonTitles:nil];
self.view.userInteractionEnabled = YES;
[alrt show];
}
else{
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle:#"LogIn Failed. Try again." message:#"User not authenticated" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
self.view.userInteractionEnabled = YES;
[alrt show];
}
}
});
}
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.spinner stopAnimating];
[numEntered setText:#"0"];
text = #"";
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle:#"Requested file does not exist." message:#"Try again." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
self.view.userInteractionEnabled = YES;
[alrt show];
});
}
}];
[task resume];
}

Since I can not comment I am writing as an Answer.
You need to check the error object to see the type of error that occured.
so in your else block you need to check error.localizedDescription to see what has happened, it would usually tell you that the file was not found or if the request timed out. you can even use your alert to show it like changing your else block as follows
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.spinner stopAnimating];
[numEntered setText:#"0"];
text = #"";
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle : #"Error"
message : error.localizedDescription
delegate : self
cancelButtonTitle : #"Ok"
otherButtonTitles : nil];
self.view.userInteractionEnabled = YES;
[alrt show];
});
}

You must use this delegate method to handle timeout:-
-(void) connection:(NSURLConnection * ) connection didFailWithError:(NSError *)error {
if (error.code == NSURLErrorTimedOut)
// handle error as you want
NSLog(#"Request time out");
}

Related

Priority execution of methods i iOS

I'm developing an application that should login to a remote service in the first view controller I create a UI to insert username and password.
When I press on the button login I make the following check:
I check if the field aren't empty with a simple if
From my button starts a segue to the internal view controller, before it shows me the internal view controller I added a method that should check if the user can login or not. In this method I call an external class in which I do the connection to the server to authenticate the user
The method to call the external class is the follow:
- (BOOL)loginSuccessWith:(NSString*)userName and:(NSString*)password {
ConnectionHandler *connectionHandler = [[ConnectionHandler alloc]init];
if ([connectionHandler startConnectionToServer:#"serverAddress" andUsername:userName withPassword:password andInstallationId:[[NSUserDefaults standardUserDefaults] objectForKey:#"instId"]]) {
return YES;
} else {
return NO;
}
}
As you can see if the method return YES or NO if the user can be logged or not.
In the ConnectionHandler class I wrote the following code:
#import "ConnectionHandler.h"
#interface ConnectionHandler() {
BOOL authenticated;
}
#end
#implementation ConnectionHandler
- (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId {
if (![self sendRequestToURL:address withMethod:#"POST" withUsername:username withPassword:password andInstallationId: installationId]) {
NSLog(#"Impossibile connettersi");
return NO;
} else {
if (authenticated) {
return YES;
} else {
return NO;
}
}
}
- (id)sendRequestToURL:(NSString *)url withMethod:(NSString *)method withUsername:(NSString*)username withPassword:(NSString*)password andInstallationId:(NSString*)installationId {
NSURL *finalURL = [[NSURL alloc]init];
if ([method isEqualToString:#"POST"]) {
finalURL = [NSURL URLWithString:url];
} else {
NSLog(#"Metodo no previsto");
}
NSString *post = [NSString stringWithFormat:#"username=%#&password=%#&installationId=%#", username, password, installationId];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)postData.length];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:finalURL];
[request setHTTPMethod:method];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
if (connection) {
[connection start];
}
return connection;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
self.responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Parsing della risposta dal server parlare con Giancarlo per vedere che tipo di risposta ottengo
NSDictionary *json;
NSError *err;
json = [NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:&err];
if (err) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"Impossibile satbilire una connessione con il server" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
} else {
NSString *error_code = [NSString stringWithFormat:#"%#", [json objectForKey:#"error_code"]];
int success = [[json objectForKey:#"success"] intValue];
NSString *error_desc = [NSString stringWithFormat:#"%#", [json objectForKey:#"error_desc"]];
if ([self autenthicationOkWithErrorCode:error_code withSuccess:success andErrorDesc:error_desc]) {
authenticated = YES;
} else {
authenticated = NO;
}
}
}
- (BOOL)autenthicationOkWithErrorCode:(NSString*)error_code withSuccess:(int)success andErrorDesc:(NSString*)error_desc {
int errCode = [error_code intValue];
if (success == 1) {
return YES;
} else if (success == 0) {
if (errCode == 2) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"Controlla di aver inserito username, password e di avere un installationId" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return NO;
}
if (errCode == 3) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"Credenziali non valide, inserisci username e password corrette" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return NO;
}
if (errCode == 4) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"Utente non autorizzato ad accedere al servizio" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return NO;
}
if (errCode == 5) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"L'utenza a cui stai cercando di accedere è già associata ad un utente diverso" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return NO;
}
if (errCode == 6) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"AT Brain" message:#"Installation ID errato" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return NO;
}
}
return NO;
}
I can connect to the server without problem, but before the - (void)connectionDidFinishLoading:(NSURLConnection *)connection is called it execute all the code in the - (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId and it returns NO so the segue in the login view controller doesn't work because the method -(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender returns NO.
So my problem is how to wait the execution of the method - (void)connectionDidFinishLoading:(NSURLConnection *)connection is done before execute the else section in method - (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId?
I hope you understand my issue and I hope you will help me to fix it, thank you
NSURLConnection is asynchronous. You kick it off and it immediately returns. You get callbacks (such as connectionDidFinishLoading) when it completes. That's the point at which you can check for success and move onto the next step.
I assume that loginSuccessWith:and: is called on the main thread (this is a very strange name for a method; you probably meant loginWithUsername:password:). So it can't block waiting for a network request that may take a very long time to complete. You'd hang the entire UI.
The URL Loading System Programming Guide has a great deal of information on how to design this. Look first at NSURLSession, and if it doesn't meet your needs, then use the lower-level NSURLConnection. With NSURLSession, you can pass completion blocks that will run whenever the operation completes.

[[BoxSDK sharedSDK].foldersManager createFolderWithRequestBuilder:builder success:success failure:failure] not working

I am having trouble creating a folder in box.com Here is my code. I am having trouble with foldersManager createFolderWithRequestBuilder If I breakpoint on the return I get "op = POST https://api.box.com/2.0/folders"
- (void)boxAPIAuthenticationDidSucceed:(NSNotification *)notification
{
NSLog(#"Received OAuth2 successfully authenticated notification");
BoxOAuth2Session *session = (BoxOAuth2Session *) [notification object];
NSLog(#"Access token (%#) expires at %#", session.accessToken, session.accessTokenExpiration);
NSLog(#"Refresh token (%#)", session.refreshToken);
dispatch_sync(dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
BoxFolderBlock success = ^(BoxFolder *folder)
{
[self fetchFolderItemsWithFolderID:self.folderID name:self.navigationItem.title];
};
BoxAPIJSONFailureBlock failure = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSDictionary *JSONDictionary)
{
NSLog(#"folder create failed with error code: %i", response.statusCode);
if (response.statusCode == 409)
{
dispatch_sync(dispatch_get_main_queue(), ^{
UIAlertView *conflictAlert = [[UIAlertView alloc] initWithTitle:#"Name conflict" message:[NSString stringWithFormat:#"A folder already exists with the name %#.\n\nNew name:", #"ezMedRecords"] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
conflictAlert.alertViewStyle = UIAlertViewStylePlainTextInput;
[conflictAlert show];
});
}
};
BoxFoldersRequestBuilder *builder = [[BoxFoldersRequestBuilder alloc] init];
builder.name = #"ezMedRecords";
builder.parentID = self.folderID;
BoxAPIJSONOperation *op;
op = [[BoxSDK sharedSDK].foldersManager createFolderWithRequestBuilder:builder success:success failure:failure];
return;
}
What is self.folderID?
It should be a valid folderID of the folder that exists on Box.
To save to "all files", start with builder.parentID = #"0";
BTW, what is error message that you get in your failure block?
Does failure block execute at all?
I'm talking about this line:
NSLog(#"folder create failed with error code: %i", response.statusCode);

Showing UIActivityIndicator when calling a webservice

I need to show a UIActivityIndicator while i am waiting for response from the web service. Where exactly do i put the code for it?? It does not work this way. the activity indicator does not show up.
Do i need to use asynchronous request in order to show it??
-(void)callWebService
{
[self.customercareSearchbar resignFirstResponder];
[self.SRResultDictionary removeAllObjects];
NSLog(#"web service called");
NSString *srn = _SRNumber;
NSString *serviceURL = [NSString stringWithFormat:#"https://abcdef...];
#try {
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:activity];
activity.center = self.view.center;
[self.view bringSubviewToFront:loadView];
activity.hidesWhenStopped = YES;
[activity setHidden:NO];
[activity startAnimating];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:serviceURL]];
NSURLResponse *serviceResponse = nil;
NSError *err = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&serviceResponse error:&err];
[activity stopAnimating];
NSMutableDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&err];
if(!parsedData)
{
NSLog(#"data not parsed");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Problem in Network. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[self.customerCareTableView setHidden:YES];
}
else
{
NSLog(#"parsed");
NSLog(#"parsed.. the size is %lu", (unsigned long)[parsedData count]);
NSLog(#"%#", parsedData);
NSString *status = [parsedData objectForKey:#"ns:Status"];
NSLog(#"the status is %#", status);
if([status isEqualToString:#"Success"])
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if([[prefs objectForKey:#"SwitchState"] isEqualToString:#"OFF"])
{
//do nothing
}
else
{
[self saveNumberInDatabase:srn];
}
NSMutableDictionary *third = [parsedData objectForKey:#"ListOfXrxLvServiceRequest"];
NSLog(#"internal dict is %#", third);
self.SRResultDictionary = [third objectForKey:#"ServiceRequest"];
[self.customerCareTableView reloadData];
[self.customerCareTableView setHidden:NO];
}
else if([status isEqualToString:#"Record Not Found"])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Invalid Entry" message:#"Please enter a valid Service Request Number" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[self.customerCareTableView setHidden:YES];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Problem in Network. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[self.customerCareTableView setHidden:YES];
}
}
}
#catch (NSException *exception)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NULL message:#"Problem In Network Connection. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[self.customerCareTableView setHidden:YES];
}
#finally {
}
}
Yes, problem is the Synchronous request.
If it is fine to send ASynchronous request then try doing this.
[NSURLConnection sendAsynchronousRequest:request queue:nil completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// stop activity
// write other code you want to execute
}];
I found MBProgressHUD is best indicator and you can use is simply in your starting of method call like
dispatch_async(dispatch_get_main_queue(), ^{
if(!HUD) HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.view addSubview:HUD];
HUD.delegate = self;
HUD.userInteractionEnabled = NO;
HUD.labelText = #"Saving your Preferences...";
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[HUD show:YES];
});
and in your finally block you can hide this like
dispatch_async(dispatch_get_main_queue(), ^{
[HUD hide:YES];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
});
//.h file
#interface ViewController : UIViewController
{
UIActivityIndicatorView *activityIndicator;
BOOL showingActivityIndicator;
}
#property(nonatomic) BOOL showingActivityIndicator;
#property(nonatomic) UIActivityIndicatorView *activityIndicator;
#end
//.m file
#synthesize showingActivityIndicator,activityIndicator;
///// Call this method in viewDidLoad
-(void)initializeClass
{
self.activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
self.activityIndicator.hidesWhenStopped = YES;
[self layoutSubviews];
}
-(void)layoutSubviews
{
CGRect activityIndicatorFrame = self.activityIndicator.frame;
activityIndicatorFrame.origin.x = (self.view.frame.size.width - self.activityIndicator.frame.size.width) / 2;
activityIndicatorFrame.origin.y = (self.view.frame.size.height - self.activityIndicator.frame.size.height) / 2;
self.activityIndicator.frame = activityIndicatorFrame;
[self.view addSubview:self.activityIndicator];
}
-(void)setShowingActivityIndicator:(BOOL)showingActivityIndicators
{
if (showingActivityIndicators) {
[self.activityIndicator startAnimating];
} else {
[self.activityIndicator stopAnimating];
}
showingActivityIndicator= showingActivityIndicators;
}
-(void)dummyButtonAction // you button action to call service
{
[self setShowingActivityIndicator:YES];
[self performSelector:#selector(callWebService) withObject:nil afterDelay:0.3];
// [self callWebService];
}
-(void)callWebService
{
[self.view endEditing:YES]; // this statement will make sure keyboard is resigned
//[self.SRResultDictionary removeAllObjects];
NSLog(#"web service called");
NSString *srn = _SRNumber;
NSString *serviceURL = [NSString stringWithFormat:#"https://abcdef...];
#try {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:serviceURL]];
NSURLResponse *serviceResponse = nil;
NSError *err = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&serviceResponse error:&err];
NSMutableDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&err];
if(!parsedData)
{
NSLog(#"data not parsed");
[self ShowAlertViewWithTitleString:#"ERROR":#"Problem in Network. Please Try Again!"];
[self.customerCareTableView setHidden:YES];
}
else
{
NSLog(#"parsed");
NSLog(#"parsed.. the size is %lu", (unsigned long)[parsedData count]);
NSLog(#"%#", parsedData);
NSString *status = [parsedData objectForKey:#"ns:Status"];
NSLog(#"the status is %#", status);
if([status isEqualToString:#"Success"])
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if([[prefs objectForKey:#"SwitchState"] isEqualToString:#"OFF"])
{
//do nothing
}
else
{
[self saveNumberInDatabase:srn];
}
NSMutableDictionary *third = [parsedData objectForKey:#"ListOfXrxLvServiceRequest"];
NSLog(#"internal dict is %#", third);
self.SRResultDictionary = [third objectForKey:#"ServiceRequest"];
[self.customerCareTableView reloadData];
[self.customerCareTableView setHidden:NO];
}
else if([status isEqualToString:#"Record Not Found"])
{
[self ShowAlertViewWithTitleString:#"Invalid Entry":#"Please enter a valid Service Request Number"];
[self.customerCareTableView setHidden:YES];
}
else
{
[self ShowAlertViewWithTitleString:#"ERROR":#"Problem in Network. Please Try Again!"];
[self.customerCareTableView setHidden:YES];
}
}
}
#catch (NSException *exception)
{
[self ShowAlertViewWithTitleString:#"":#"Problem In Network Connection. Please Try Again!"];
[self.customerCareTableView setHidden:YES];
}
#finally {
}
[self setShowingActivityIndicator:NO];
}
- (void)ShowAlertViewWithTitleString :(NSString *)title :(NSString *)message
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}

UIActivityIndicatorView Not Stopping When I want

I need to show a UIActivityIndicatorView when calling of a WebService is take place. However, the activity indicator keeps on showing even after i have received response from web service. It stops only after 5-6 seconds after i receive response. How to make it stop at the moment i am receiving a response?
Here's my code: (configuring UIActivityIndicatorView) and calling my webservice:
loadView = [[UIView alloc] initWithFrame:self.view.bounds];
loadView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.5];
//UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] init];
//[second.loadingView addSubview:activityView];
//activityView.center = second.loadingView.center;
//[second.view addSubview:second.loadingView];
activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[loadView addSubview:activity];
activity.center = loadView.center;
[self.view addSubview:loadView];
[self.view bringSubviewToFront:loadView];
activity.hidesWhenStopped = YES;
[activity setHidden:NO];
//[activity performSelectorInBackground: #selector(startAnimating) withObject: nil];
[activity startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self callRegisterWebService:self.userFname lastName:self.userLName email:self.userEmail];
});
I am stopping the animation in the finally block.
-(void)callRegisterWebService:(NSString *)fname lastName:(NSString *)lName email:(NSString *)email
{
NSString *serviceURL = [NSString stringWithFormat:#"https:abcdefghi..."];
#try {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:serviceURL]];
NSURLResponse *serviceResponse = nil;
NSError *err = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&serviceResponse error:&err];
NSMutableDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&err];
if(!parsedData)
{
NSLog(#"data not parsed");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Problem in Network. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
else
{
NSString *status = [parsedData objectForKey:#"Status"];
if([status isEqualToString:#"Success"])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NULL message:#"Authentication Token Has Been Sent To Your Email-ID!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
NSString *uniqueNumber = [parsedData objectForKey:#"UniqueNum"];
[self saveEmailAndUniqueNumberToDatabase:fname lastName:lName Email:email Number:uniqueNumber];
}
else if([status isEqualToString:#"Failed"])
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Not An Authorized User" message:#"Please Contact Admin To Get Access" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"ERROR" message:#"Problem in Network. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}
}
#catch (NSException *exception)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NULL message:#"Problem In Network Connection. Please Try Again!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
#finally {
[activity stopAnimating];
[loadView setHidden:YES];
}
}
There are 2 issues in your code:
You are manipulating UI component from a background thread, never do that. Use main thread for UI manipulations
You wrote the activity indicator functionality in the finally clause, so it'll be hidden only after executing all the statements in try clause
Change your method like:
- (void) hideActivity
{
dispatch_async(dispatch_get_main_queue(), ^{
[activity stopAnimating];
[loadView setHidden:YES];
activity = nil;
loadView = nil;
});
}
-(void)callRegisterWebService:(NSString *)fname lastName:(NSString *)lName email:(NSString *)email
{
NSString *serviceURL = [NSString stringWithFormat:#"https:abcdefghi..."];
NSString *message = #"";
NSString *title = #"";
#try
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:serviceURL]];
NSURLResponse *serviceResponse = nil;
NSError *err = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&serviceResponse error:&err];
NSMutableDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&err];
[self hideActivity];
if(!parsedData)
{
message = #"Problem in Network. Please Try Again!";
title = #"ERROR";
}
else
{
NSString *status = [parsedData objectForKey:#"Status"];
if([status isEqualToString:#"Success"])
{
message = #"Authentication Token Has Been Sent To Your Email-ID!";
title = nil;
NSString *uniqueNumber = [parsedData objectForKey:#"UniqueNum"];
[self saveEmailAndUniqueNumberToDatabase:fname lastName:lName Email:email Number:uniqueNumber];
}
else if([status isEqualToString:#"Failed"])
{
message = #"Please Contact Admin To Get Access";
title = #"Not An Authorized User";
}
else
{
message = #"Problem in Network. Please Try Again!";
title = #"ERROR";
}
}
}
#catch (NSException *exception)
{
if (activity != nil && loadView != nil)
{
[self hideActivity];
}
message = #"Problem In Network Connection. Please Try Again!";
title = nil;
}
#finally
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
}

UICollectionView Tap events

i've created a UICollectionView inside a ViewController. My UiCollectionViewCell contains a imageview and a label. It seems like it is really bad at handling click events. i need to click a lot of times before it react for the click. often it only do it on double tap.
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *urlString2 = [NSString stringWithFormat:#"http://ratemyplays.com/songs.php?listid=%d", indexPath.row];
NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc]init];
[request2 setTimeoutInterval:20.0];
[request2 setURL:[NSURL URLWithString:urlString2]];
[request2 setHTTPMethod:#"POST"];
NSString *PHPArray = [[NSString alloc] initWithData:[NSURLConnection sendSynchronousRequest:request2 returningResponse:nil error:nil] encoding:NSUTF8StringEncoding];
NSArray *playArray2 = [PHPArray componentsSeparatedByString:#"."];
if ([playArray2 count] <2) {
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"This Playlist is empty!!" message:#"We're Currently modifying it" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert2 show];
} else {
YouTubeTableViewController *youTubeTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"YouTubeTableViewController"];
youTubeTableViewController.selectedRowValue=indexPath.row;
[self.navigationController pushViewController:youTubeTableViewController animated:YES];
youTubeTableViewController.titleName = scoreArray;
youTubeTableViewController.playlistId = scoreArray2;
}
}
Is this normal behavior or am i missing something?
You are doing a synchronous request when the cell is clicked, and it may be causing this "feeling" that you have to click several times. I suggest you change the NSURLConnection synchronous request to an asynchronous one. Like this:
[NSURLConnection sendAsynchronousRequest:request
queue:[[NSOperationQueue alloc] init]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if (error == nil)
{
NSString *PHPArray = =[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"data received from url: %#", PHPArray);
if ([playArray2 count] <2) {
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"This Playlist is empty!!" message:#"We're Currently modifying it" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert2 show];
} else {
YouTubeTableViewController *youTubeTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"YouTubeTableViewController"];
youTubeTableViewController.selectedRowValue=indexPath.row;
[self.navigationController pushViewController:youTubeTableViewController animated:YES];
youTubeTableViewController.titleName = scoreArray;
youTubeTableViewController.playlistId = scoreArray2;
}
}
else if (error != nil && error.code == NSURLErrorTimedOut)
{
NSLog(#"error code: %ld", (long)error.code);
}
else if (error != nil)
{
NSLog(#"error code: %ld", (long)error.code);
}
}];
Do you have your label and image enabled for user interaction?

Resources