How to call my view controller method into appdelegate.m? - ios

I am having action for login button in view controller but i have to use some condition in appdelegate.m that if user logged in already then viewcontroller login action method will fire and if not logged in then only login page will open?
Please help me
in AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[NSUserDefaults standardUserDefaults]boolForKey:#"IsFirstTime"])
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
HomePageVC *lvc = [storyboard instantiateViewControllerWithIdentifier:#"HomePageVC"];
[(UINavigationController *)self.window.rootViewController pushViewController:lvc animated:NO];
}
else
{
[[NSUserDefaults standardUserDefaults]setBool:YES forKey:#"IsFirstTime"];
[[NSUserDefaults standardUserDefaults]synchronize];
}
return YES;
}
in viewcontroller.m
- (IBAction)Login:(id)sender
{
[self.indicator startAnimating];//The ActivityIndicator Starts Animating Here
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:BaseUrl#"login"]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"*/*" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"];
NSString *mapData = [NSString stringWithFormat:#"userName=gautam.kar#eyeforweb.com&userPassword=1234567&api_key=ZWZ3QDEyMw==&api_password=456789"];
NSData *postData = [mapData dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error == nil)
{
NSString *text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"jsondic= %#",jsonDic);
NSDictionary *userDataDic = [jsonDic objectForKey:#"record"];
[DataModel setEmailAdd:[userDataDic objectForKey:#"emailAdd"]];
[DataModel setName:[userDataDic objectForKey:#"Name"]];
[DataModel setCity:[userDataDic objectForKey:#"city"]];
[DataModel setCountry:[userDataDic objectForKey:#"country"]];
[DataModel setRegistrationID:[userDataDic objectForKey:#"registrationID"]];
[DataModel setPhoneNo:[userDataDic objectForKey:#"phoneAdd"]];
[DataModel setState:[userDataDic objectForKey:#"state"]];
[DataModel settimeZone:[userDataDic objectForKey:#"timezone"]];
[DataModel setDisclaimer:[userDataDic objectForKey:#"disclaimer"]];
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];//The ActivityIndicator Stops Animating when Response Arrives
NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"text= %#",text);
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
[self checkUserSuccessfulLogin:json];
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];
});
NSLog(#"Error : %#",error.description);
}
}];
[postDataTask resume];
}
- (void)checkUserSuccessfulLogin:(id)json
{
// NSError *error;
NSDictionary *dictionary = (NSDictionary *)json;
if ([[dictionary allKeys] containsObject:#"login"])
{
if ([[dictionary objectForKey:#"login"] boolValue])
{
NSString *strID = [[NSUserDefaults standardUserDefaults] stringForKey:#"textField1Text"];
NSString *strPWD = [[NSUserDefaults standardUserDefaults] stringForKey:#"textField2Text"];
[[NSUserDefaults standardUserDefaults] setValue:[dictionary objectForKey:#"user_id"] forKey:#"CurrentUserLoggedIn"];
NSString *strUser = [[NSUserDefaults standardUserDefaults] stringForKey:#"CurrentUserLoggedIn"];
[[NSUserDefaults standardUserDefaults]synchronize];
[self saveLoginFileToDocDir:dictionary];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
HomePageVC *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"HomePageVC"];
[self.navigationController pushViewController:vc animated:YES];
}
else
{
NSLog(#"Unsuccessful, Try again.");
UIAlertView *alertLogin = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Wrong Username Or Password" delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:nil];
[alertLogin show];
}
}
}
- (void)saveLoginFileToDocDir:(NSDictionary *)dictionary
{
NSArray *pListpaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *pListdocumentsDirectory = [pListpaths objectAtIndex:0];
NSString *path = [pListdocumentsDirectory stringByAppendingPathComponent:#"Login.plist"];
BOOL flag = [dictionary writeToFile:path atomically:true];
if (flag)
{
NSLog(#"Saved");
}
else
{
NSLog(#"Not Saved");
}
}
- (NSDictionary *)getLoginFileFromDocDir
{
NSArray*pListpaths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString*pListdocumentsDirectory = [pListpaths objectAtIndex:0];
NSString *path = [pListdocumentsDirectory stringByAppendingPathComponent:#"Login.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
return dict;
}

What you need is not to check your controller in AppDelegate.m, even though that is what you're asking.
Your real problem is " how can I access data from two different places ? ".
Right now, you're telling AppDelegate he "knows" your view controllers. It shouldn't.
What you need is one (actually a lot more but you'll learn that with time) new class, that handles the Login calls and state, and all that is login related.
Call that class the... LoginManager.
In that class, you could have some methods, like Login() or Logout(), or anything you would like.
Now you have an external source of data, your login manager knows everything he musts knows about the login. You should even add some properties, like a boolean IsLoggedIn or anything you might need.
And that source of data is what AppDelegate needs to know. Not the controllers. With that kind of architecture, EVERYONE that needs the login information can access it from that class (which could / should be a singleton class, look it up on the internet, its very easy.
In your viewcontroller, you can simply do Loginmanager.login, and in appdelegate, you can check .isloggedin.
That helps you a lot, because you don't have to instantiate view controllers in appdelegate, which is really a lot of work. You're splitting the work and the tasks between classes, which is what a good programmer does. Remember, your class should have only one job, not more, not less. Your VC handles the user inteface, not the webservic calls, not the login, nothing. If it does, it means you need to create another class :)
Once you've implemented all that (read my answer as many times as necessary to make sure you understand), you'll have no problem accessing that kind of data in other place of your app.
Note that you shouldn't abuse singleton classes or static classes (especially static), but again, you'll probably make many mistakes and learn from them, like we all did when we started.

Create your ViewController Object like below,
viewcontroller *objYourVC=[[viewcontroller alloc]init];
Now call method from Appdelegate like below:
[objYourVC functionToBeCalled:nil];
OR
[objYourVC functionToBeCalled:self];
Example,
if(AlreadyLogin){
//call viewcontroller method
viewcontroller *objYourVC=[[viewcontroller alloc]init];
[objYourVC functionToBeCalled:nil];
}

Related

PrepareForSegue called before didSelectRowAtIndexPath

I am calling the following method in didSelectRowAtIndexPath.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{
[self unreadMessageCounter];
}
In that method I am getting a value with parameter name "MsgCount". For that the written code is.
-(void) unreadMessageCounter{
NSUserDefaults *defaultUser=[NSUserDefaults standardUserDefaults];
NSString* username = [defaultUser objectForKey:KUserName];
NSString* password = [defaultUser objectForKey:KPassword];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showWithStatus:#"Loading..." maskType:SVProgressHUDMaskTypeGradient];
});
NSString *url3 ;
NSString *base_url=[[NSUserDefaults standardUserDefaults] objectForKey:#"BASE_URL"];
url3=[[NSString alloc]initWithFormat:#"%#%#? username=%#&password=%#&deviceUniqueId=%#",base_url,MESSAGE_COUNTER,username,password,[defaultUser objectForKey:KDeviceToken]];
[defaultUser synchronize];
NSURL *requestURL = [NSURL URLWithString:[url3 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:requestURL];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *urlResponse, NSError *error) {
NSHTTPURLResponse *response = (NSHTTPURLResponse *)urlResponse;
NSLog(#"Response Code For Message Counter:: %ld", (long)[response statusCode]);
if(response){
NSMutableDictionary *returneDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"Return Dict For Message Counter:: %#", returneDict);
if (returneDict != nil) {
if ([returneDict valueForKey:#"valueSet"]){
for (NSDictionary *dict in [returneDict valueForKey:#"valueList"]) {
_counterNumber = dict[#"MsgCount"];
NSLog(#"counter number %#", _counterNumber);
}
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}
}
}];
[task resume];
}
After that I am passing that _counterNumber string to the next view controller with the help of prepareForSegue, for that the following code is.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (![segue.identifier isEqualToString:#"Show Notification"]) {
UINavigationController *nav = [segue destinationViewController];
WelcomeScreenViewController *welcomeScreenViewController = (WelcomeScreenViewController *)nav.topViewController;
welcomeScreenViewController.counterString = _counterNumber;
}
}
It was going to the next view controller but on the first call, after didselectrowatindexpath instead of unreadMessageCounter method, prepareForSegue is getting call that's why the _counterNumber value I am getting nil, but on the second time when I am calling then It is working as usual. So plese help me in that case because I am not getting any clue.
First Disconnect your segue from cell to nextViewController. And make new segue from current ViewController to your nextViewController like below screenshot
And after processing you API that you are calling in didSelectRowAtIndexPath perform segue through code like below.
[self performSegueWithIdentifier: #"Show Notification" sender: self];

login and completion handler

I'm developing an app with a login page. When the app is launched, the login screen is shown, and you cannot access the app until you are connected. To connect to the app, you enter your username and your password. When you press the "connect" button, json data containing the username and password is sent to a web service, which check if the credentials exists. If they exists, the server send a json file containing "exists":"true"
The problem is that the code checking this Json file is in completionHandler of my NSURLSession, and the method return "NO" before the Json data is checked, so I can not connect to my app. As it's hard to explain, here is my code:
GSBconnexion.m:
#import "GSBconnexion.h"
#implementation GSBconnexion
-(bool)logConnexionWithUserName:(NSString *)username
password:(NSString *)password{
__block BOOL allowConnexion;
NSDictionary *connexion = #{
#"username": username,
#"password": password,
#"target": #"app"
};
NSError *error;
NSData *jsonLogData = [NSJSONSerialization dataWithJSONObject:connexion options:NSJSONWritingPrettyPrinted
error:&error];
if (! jsonLogData) {
NSLog(#"Got an error: %#", error);
}
NSData *logData = jsonLogData;
NSString *testString = [[NSString alloc] initWithData:logData encoding:NSUTF8StringEncoding];
NSString *logLength = [NSString stringWithFormat:#"%lu", (unsigned long)[testString length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://192.168.5.133:1337/login"]];
[request setHTTPMethod:#"POST"];
[request setValue:logLength forHTTPHeaderField:#"Content-lenght"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:logData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSDictionary *serverResponse = [NSJSONSerialization JSONObjectWithData:data options:
NSJSONReadingMutableContainers error:&error];
int canIConnect = [serverResponse[#"exist"] intValue];
NSLog(#"%d",canIConnect);
if (canIConnect == 1) {
NSLog(#"OKKK");
allowConnexion = YES;
NSString *sessionID = [[NSString alloc]initWithString:serverResponse[#"_id"]];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:sessionID forKey:#"SessionID"];
[userDefaults synchronize];
NSLog(#"ID Session:%#",[userDefaults objectForKey:#"sessionID"]);
}
else {
allowConnexion=NO;
}
}] resume];
NSLog(#"JSON envoyé: \n\n%#",testString);
return allowConnexion;
}
#end
GSBLoginController:
- (IBAction)connect:(id)sender {
connectButton.hidden = YES;
loading.hidden = NO;
UIViewController* homePage = [self.storyboard instantiateViewControllerWithIdentifier:#"homePage"];
GSBconnexion *login = [[GSBconnexion alloc]init];
NSString *username = [[NSString alloc]initWithFormat:#"%#",usernameTextField.text];
NSString *password = [[NSString alloc]initWithFormat:#"%#",pwdTextField.text];
BOOL authorized = [login logConnexionWithUserName:username password:password];
if (authorized) {
[self presentViewController:homePage animated:YES completion:nil];
}
else {
connectButton.hidden = NO;
loading.hidden=YES;
usernameTextField.text=#"";
pwdTextField.text=#"";
errorLabel.text = #"Connexion impossible, merci de réessayer.\nSi le problème persiste, veuillez contacter un administrateur.";
}
NSLog(authorized ? #"Yes" : #"No");
}
I hope you understood me, thanks for your help!
Simon
The problem is that you're expecting a return value from a method that is executing asynchronously. So basically return allowConnexion is happening immediately even though the dataTask is still ongoing in the background. Thus, you're relying on an incorrect value. Basically what you want to do is copy what is happening in the dataTask w/ a completion handler.
So you could say something like typedef void (^CompletionBlock) (BOOL isFinished);
Then change your login method to include the completion block as its last argument and return nothing:
-(void)logConnexionWithUserName:(NSString *)username
password:(NSString *)password
withCompletion:(CompletionBlock)completionBlock
Then inside of the dataTask's completionHandler call the completionBlock passing in the value of allowConnexion.
Finally once you've done all that in your login view controller you'll implement this new method, and inside of the completion block you can update your view accordingly. Its going to look something like this:
- (void)thingWithCompletion:(CompletionBlock)completionBlock
{
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(YES);
});
}
- (void)viewDidLoad {
[super viewDidLoad];
[self thingWithCompletion:^(BOOL isFinished) {
//update UI
}];
}
Be advised that since you're on a background thread and going to update UI on completion you're going to want to dispatch to the main queue as well. That is why the call to completionBlock(YES); is wrapped in the dispatch_async call.

Delay displaying a LoginViewController

I have this app that uses an accessToken that only remains for two hours. My app has three UINavigationController (with UITableViewController) inside a UITabBarController. Every time I click on one of my tabs, a new connection is created and I check if the statusCode of the HTTP response is 200 or 401. If the statusCode is 401 is because my accessToken is no longer operative and I have to relog again.
The problem I have is that when the current viewController calls the LoginViewController because the 401, the LoginViewController shows with delay and you can see the cells of UITableViewController.
My code is:
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[CaseCell class] forCellReuseIdentifier:#"identifier"];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.accessToken = [userDefaults objectForKey:#"accessToken"];
if (self.accessToken == nil) {
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[self presentViewController:loginViewController animated:NO completion:nil];
} else {
[self refresh];
}
}
- (void)refresh
{
NSURLSession *session = [NSURLSession sharedSession];
NSString *urlString = [[NSString alloc] initWithFormat:#"myURL", self.accessToken];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSData *data = [[NSData alloc] initWithContentsOfURL:location];
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = [httpResponse statusCode];
if (statusCode == 200) {
NSArray *responseArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
self.cases = responseArray;
}
dispatch_async(dispatch_get_main_queue(), ^{
if (statusCode == 200) {
[self.tableView reloadData];
} else {
LoginViewController *loginViewController = [[LoginViewController alloc] init];
[self presentViewController:loginViewController animated:NO completion:nil];
}
});
}];
[task resume];
}
I really don't know what is the problem. I mean, I know it has to be related with things happening in background and dispatch_async but I've made everything and I don't know why this delay.
PD: Don't pay attention to NSUserDefaults. I know I have to store the token in Keychain.
THANK YOU VERY MUCH!
You could use the delegate method
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
that gets called by your UITabBarController to check that the session is still valid, and then either proceed to the view controller or launch your login controller. If you try adding it to the view controller's view before the view loads, it won't have anything to add it to, and if you call it after the view loads, you're going to see the original view before it can launch the login screen.

Update the UI of the View Controller and then dismiss it

I have a view controller, that loads some an array. While everything is loading, I need to present another view controller (with the UIProgressView) and update it's UI (the progress property of a UIProgressView) and then dismiss and present first vc with downloaded data. I'm really struggling on it and I've tried delegation, but nothing worked for me.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"downloaded"]) {
} else {
NSLog(#"First time Launched");
ProgressIndicatorViewController *progressVC = [ProgressIndicatorViewController new];
progressVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self syncContacts];
[self presentViewController:progressVC animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"downloaded"];
[progressVC release];
}
}
sync contacts method:
- (void)syncContacts
{
NSLog(#"Sync data");
NSMutableArray *allContacts = [ContactsOperations getAllContactsFromAddressBook];
NSInteger allContactsCount = [allContacts count];
if (allContactsCount > 0) {
for (ContactData *contact in allContacts) {
NSMutableArray *phoneNumbersArray = [[NSMutableArray alloc] init];
NSString *nospacestring = nil;
for (UserTelephone *tel in [contact.abonNumbers retain]) {
NSArray *words = [tel.phoneNumber componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceCharacterSet]];
NSString *nospacestring = [words componentsJoinedByString:#""];
[phoneNumbersArray addObject:nospacestring];
}
contact.abonNumbers = phoneNumbersArray;
if (phoneNumbersArray != nil) {
NSLog(#"NOT NULL PHONENUMBERS: %#", phoneNumbersArray);
}
NSDictionary *dataDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:contact.abonNumbers, #"phoneNumbers", contact.contactName, #"fullName", [NSNumber numberWithBool:contact.isBlackList], #"blacklist", [NSNumber numberWithBool:contact.isIgnore], #"ignore", contact.status, #"status", nil];
NSLog(#"dictionary: %#", dataDictionary);
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDictionary options:0 error:&error];
NSLog(#"POST DATA IS : %#", postData);
NSMutableURLRequest *newRequest = [self generateRequest:[[NSString stringWithFormat:#"%#c/contacts%#%#", AVATATOR_ADDR, SESSION_PART, [[ServiceWorker sharedInstance] SessionID]] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] withHTTPMethod:#"POST"];
[newRequest setHTTPBody:postData];
[newRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//__block NSMutableData *newData;
[NSURLConnection sendAsynchronousRequest:newRequest queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (!connectionError) {
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"alldata from contacts: %#", allData);
//NSInteger errorCode = [[allData objectForKey:#"CommandRes"] integerValue];
//if (errorCode == 0) {
NSInteger remoteId = [[allData objectForKey:#"contactId"] integerValue];
contact.remoteId = remoteId;
NSLog(#"remote id is from parse content : %d", remoteId);
[[AvatatorDBManager getSharedDBManager]createContactWithContactData:contact];
} else {
NSLog(#"error");
}
}];
//Somewhere here I need to update the UI in another VC
[phoneNumbersArray release];
[dataDictionary release];
}
} else {
}
}
generate request method:
- (NSMutableURLRequest *)generateRequest:(NSString *)urlString withHTTPMethod:(NSString *)httpMethod
{
NSLog(#"url is :%#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
request = [NSMutableURLRequest requestWithURL:url];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[request setHTTPMethod:httpMethod];
return request;
}
ProgressViewController is just an empty VC with the progress bar. No code yet.
In the view controller that will display the progress view expose a method like this...
- (void)updateProgress:(float)progress;
Its implementation will look like this...
- (void)updateProgress:(float)progress {
[self.progressView setProgress:progress animated:YES];
}
On the main view controller you need to execute the long-running process on a background thread. Here's viewDidLoad for the main view controller. This example code uses a property for the progress view controller (you may not require this) and assumes your are in a navigation controller...
- (void)viewDidLoad {
[super viewDidLoad];
// Create and push the progress view controller...
self.pvc = [[ProgressViewController alloc] init];
[self.navigationController pushViewController:self.pvc animated:YES];
// Your long-running process executes on a background thread...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Your long-running process goes here. Wherever required you would
// call updateProgress but that needs to happen on the main queue...
dispatch_async(dispatch_get_main_queue(), ^{
[self.pvc updateProgress:progress];
});
// At the end pop the progress view controller...
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
});
}

Push to new ViewController from connectionDidFinishLoading

Is it possible to push to a new view controller from ConnectionDidFinishLoading ?
I have the following and it performs the ConnectionDidFinishLoading but does not push to new view controller.
-(void)connectionWithURLString:(NSMutableArray *)urlString
{
NSDate *now = [NSDate date];
int userID = [[clientDataStruct.clientData objectForKey:#"number"] intValue];
NSDate *date = self.datePicker.date;
// NSLog(#"obj: %#", urlString);
NSString *extrString = [NSString stringWithFormat:#", customerdetails:{customer_id = %d, job_date = %#, date_created = %#}",userID,date, now];
NSString *post = [NSString stringWithFormat:#"json=quote:{%#%#}", urlString, extrString ];
NSLog(#"post: %#", post);
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *value = [defaults objectForKey:#"value"];
NSString *jsonUrl = [NSString stringWithFormat:#"xxx?task=add_quote&user_id=%#&customer_id=%#",value, [clientDataStruct.clientData valueForKey:#"number"]];
[request setURL:[NSURL URLWithString:jsonUrl]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
if (!connection)
NSLog(#"Connection failed!");
}
- (void)Success
{
UIStoryboard *subVc = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle:nil];
UserTableView *userTable = [subVc instantiateViewControllerWithIdentifier:#"UserTableView"];
userTable.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController pushViewController:userTable animated:YES];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"%#", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self performSelectorOnMainThread:#selector(Success) withObject:Nil waitUntilDone:YES];
NSLog(#"connectionDidFinishLoading%#", connection);
}
Everything works, and returns my data and data gets added into the SQL. My NSLog shows that ConnectionDidFinishLoading. But it does not push to the new View Controller.
Thanks for the help, being scratching my head on this one.
Thanks to Fahim advise allowed me to debug further, The Navigation view broke with a returned model controller. Changed it to push and all is working
Point 1
This is not working with you because you don't have navigation controller. Make sure that you have navigation controller.
Point 2
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self performSelectorOnMainThread:#selector(LoginSuccess) withObject:Nil waitUntilDone:YES];
NSLog(#"connectionDidFinishLoading%#", connection);
}
This is something wrong. Even if user have entered incorrect username or password, you are still allowing user to get logged in.
Check the response that you are getting in connectionDidFinishLoading and then based on this response do the transition.
e.g. if you have PHP at backend your code will be
sql query here to add data
if (data added) {
echo "valid";
} else {
echo "invalid";
}
now check this response in connectionDidFinishLoading and based on this do the transition
First check that if your LoginSuccess is getting called if yes then paste this
UserTableView * userTable =[self.storyboard instantiateViewControllerWithIdentifier:#"UserTableView"];
[self.navigationController pushViewController:userTable animated:YES]
like this but replace ResultsTableView with UserTableView

Resources