Priority execution of methods i iOS - 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.

Related

Response in alert view

I am new to IOS i want to display response from post in alert view.in nslog i showed response. i need when i clicked button alert view can display my response.
coding:
-(void) sendDataToServer : (NSString *) method params:(NSString *)str{
NSData *postData = [str dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[str length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URL]];
NSLog(#"%#",str);
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURLConnection *theConnection = [NSURLConnection connectionWithRequest:request delegate:self];
if( theConnection ){
mutableData = [[NSMutableData alloc]init];
}
}
alerview:
- (IBAction)butt1:(id)sender {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Value"
message:#"%#"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok", nil];
[self sendDataToServer :#"POST" params:str];
[alert show];
}
post method delegates:
here i get response in json111 that i showed in nslog successfully but in alert view i failed
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
return;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError* error111;
json111 = [NSJSONSerialization JSONObjectWithData: mutableData
options:kNilOptions
error:&error111];
NSLog(#"%#",json111);
}
[![emptyvalue in alertview][1]][1]
change this into
updated answer
#interface myViewController : UIViewController <UIAlertViewDelegate>
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError* error111;
json111 = [NSJSONSerialization JSONObjectWithData: mutableData
options:kNilOptions
error:&error111];
NSLog(#"%#",json111);
NSArray *temp = [ json111 objectForKey:#"Currencies"];
// you can directly fetch like
NSDictionary *fetchDict = [temp objectAtIndex:0];
NSDictionary *fetchUnit = [temp objectAtIndex:1];
// finally you can fetch like
NSString * total = [fetchDict objectForKey:#"total"];
NSString * one_unit = [fetchUnit objectForKey:#"one_unit"];
//updated
NSString *final = [NSString stringWithFormat:#"%# , %#", total,one_unit];
// in here you can assign the value to Alert
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Value"
message:final
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok", nil];
alert.tag = 100;
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 100)
{
if (buttonIndex == 0)
{
// ok button pressed
//[self sendDataToServer :#"POST" params:str];
}else
{
// cancel button pressed
}
}
You should know the basics of NSString, refer here.
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Value"
message:[NSString stringWithFormat:#"%#", str]
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok", nil];
You can save your response in an NSString and then pass this string in the message field of your alert view.
However, as of iOS 8,
UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead
Change your Alert View as following :
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Value"
message:[NSString stringWithFormat:#"Response Message : %#",str]
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"ok", nil];
This will display your response message instead %#..
If you want to send Data to Server on Click on alertView, you need to write code in alertView Delegate clickedButtonAtIndex
Hope it helps..

How to check a timeout occurred in ios url connection?

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");
}

How to send app invitation to facebook friends from ios app

I have complete code for send invitation when i click on button a pop up menu is appear,in the pop up menu say...
ERROR.
Game Requests are available to games.
and my code for invite friends are here:
NSDictionary *parameters = #{#"to":#""};
[FBWebDialogs presentRequestsDialogModallyWithSession:nil
message:#"message aaya kya" title:#"app request"
parameters:parameters
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error)
{
if(error)
{
NSLog(#"Some errorr: %#", [error description]);
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle:#"Invitiation Sending Failed" message:#"Unable to send inviation at this Moment, please make sure your are connected with internet" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alrt show];
// [alrt release];
}
else
{
if (![resultURL query])
{
return;
}
NSDictionary *params = [self parseURLParams:[resultURL query]];
NSMutableArray *recipientIDs = [[NSMutableArray alloc] init];
for (NSString *paramKey in params)
{
if ([paramKey hasPrefix:#"to["])
{
[recipientIDs addObject:[params objectForKey:paramKey]];
}
}
if ([params objectForKey:#"request"])
{
NSLog(#"Request ID: %#", [params objectForKey:#"request"]);
}
if ([recipientIDs count] > 0)
{
//[self showMessage:#"Sent request successfully."];
//NSLog(#"Recipient ID(s): %#", recipientIDs);
UIAlertView *alrt = [[UIAlertView alloc] initWithTitle:#"Success!" message:#"Invitation(s) sent successfuly!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alrt show];
//[alrt release];
}
}
}
friendCache:nil];
}
so where I am wrong?
Please help me.
Thanks.
Ok,I understand if you want to send app request to your friends than you should use FBSDKAppInviteContent.
Here is the code:
FBSDKAppInviteContent *content =[[FBSDKAppInviteContent alloc] init];
content.appLinkURL = [NSURL URLWithString:#"Your_App_Id"];
content.previewImageURL = [NSURL URLWithString:#"Your_app_previewimage"];
[FBSDKAppInviteDialog showWithContent:content
delegate:self];
Here for Your_App_Id please refer to this link.
And it's delegate methods:
- (void)appInviteDialog:(FBSDKAppInviteDialog *)appInviteDialog didCompleteWithResults:(NSDictionary *)results{
if (results) {
}
}
- (void)appInviteDialog:(FBSDKAppInviteDialog *)appInviteDialog didFailWithError:(NSError *)error{
if (error) {
NSString *message = error.userInfo[FBSDKErrorLocalizedDescriptionKey] ?:
#"There was a problem sending the invite, please try again later.";
NSString *title = error.userInfo[FBSDKErrorLocalizedTitleKey] ?: #"Oops!";
[[[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}
Why don't you try FBSDKGameRequestContent(It will require Facebook SDK 4.0)?
Note: This will work only if your app category is Game in Facebook developer page.
Here is the code:
FBSDKGameRequestContent *gameRequestContent = [[FBSDKGameRequestContent alloc] init];
// Look at FBSDKGameRequestContent for futher optional properties
FBSDKGameRequestDialog *dialog = [[FBSDKGameRequestDialog alloc]init];
dialog.delegate = self;
dialog.content = gameRequestContent;
gameRequestContent.message = #"Become a Ninja!!!";
gameRequestContent.title = #"NinjaPan";
dialog.delegate = self;
dialog.content = gameRequestContent;
[dialog show];
And it's delegate methods:
- (void)gameRequestDialog:(FBSDKGameRequestDialog *)gameRequestDialog didCompleteWithResults:(NSDictionary *)results{
if (results) {
}
}
- (void)gameRequestDialog:(FBSDKGameRequestDialog *)gameRequestDialog didFailWithError:(NSError *)error{
if (error) {
NSLog(#"%#",error.localizedDescription);
}
}
- (void)gameRequestDialogDidCancel:(FBSDKGameRequestDialog *)gameRequestDialog{
NSLog(#"Cancelled by user");
}

How to resolve error:the operation couldn’t be completed. (cocoa error 3840.) json iOS?

I wrote the GET method code to retrieve the details from server(json format).But I am getting the error (the operation could not be completed).
can anyone please provide me some information regarding this?
My code:
-(void)getResponseWithOutBodywithMethod:(NSString*)method
{
NSMutableURLRequest *request =
[NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:method];
//[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// [request setTimeoutInterval:20.0];
NSURLConnection *conn=[[NSURLConnection alloc]initWithRequest:request delegate:self];
if (conn)
{
receivedData = [[NSMutableData alloc] init] ;
}
}
#pragma mark NSURLConnection delegate methods
- (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 setLength:0];
}
- (void) connection:(NSURLConnection *)connection didReceiveData: ( NSData *)data{
[receivedData appendData:data];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:( NSError *)error{
completion(nil, error);
NSLog(#"%#",[error localizedDescription]);
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection{
if (receivedData != nil) {
NSError *jsonParsingError = nil;
NSMutableDictionary *dict = [NSJSONSerialization JSONObjectWithData:receivedData
options:kNilOptions error:&jsonParsingError];
NSString* str = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSLog(#"error %#",jsonParsingError.localizedDescription);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"ER" message:str delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
if (dict == nil && [dict count]==0) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:jsonParsingError.localizedDescription delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
completion(nil, jsonParsingError);
}
else {
completion(dict, nil);
}
}
else {
completion(nil, [NSError errorWithDomain:#"http" code:-1 userInfo:nil]); //todo proper error
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Failed to get data." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alertView show];
}
}
Well I would think your Json is the problem.
If your server is responding:
Something=somethingelse
That's not the proper format. You would need to Json encode it so it looks like:
[{"key":"value", "key":"value"}]

UIWebView does not loads after any unsuccessful login

I am loading a url which has authentication So I used the following code
BOOL _authed = NO;
NSURLAuthenticationChallenge *mChallenge;
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
{
NSLog(#"Did start loading: %# auth:%d", [[request URL] absoluteString], _authed);
if (!_authed) {
_authed = NO;
[NSURLConnection alloc]initWithRequest:request delegate:self];
return NO;
}
return YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
{
NSLog(#"got auth challange");
_authed = YES;
mChallenge = challenge;
UIAlertView *prompt = [[UIAlertView alloc]initWithTitle:nil message:#"Authentication Required" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Login", nil];
prompt.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[prompt show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 1){
UITextField *usernameField = [alertView textFieldAtIndex:0];
UITextField *passwordField = [alertView textFieldAtIndex:1];
NSString *userName = usernameField.text;
NSString *password = passwordField.text;
NSLog(#"%#, %#",userName,password);
[[mChallenge sender] useCredential:[NSURLCredential credentialWithUser:userName password:password persistence:NSURLCredentialPersistencePermanent] forAuthenticationChallenge:mChallenge];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
{
NSLog(#"response %#",response);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://mysharepointurl.aspx"]];
[self.webView loadRequest:request];
}
- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection;
{
return NO;
}
this works fine if I try correct password first time.
But when I try with wrong credential first time, the prompt comes again and then I try with correct credential, then web view will not be loaded
any advice on this

Resources