0

I'm building my first iOS app with a login system. I've built some simple things before, but this is on a whole new level. Currently I'm able to login and get some data back from the server. The app then performs a model segue to MainView with MainController attached to it.

When I log in, the app gets token and success back from the server. This token is needed for further requests to the server. However, I can't seem to figure out how to pass the token to MainController. It doesn't matter what I try, the app crashes with an unknown error.

Right now - with the code below - it throws:

2014-10-11 14:30:14.077 LoginScreen[29076:4688502] -[UINavigationController setXAuthToken:]: unrecognized selector sent to instance 0x7bfd1140 2014-10-11 14:30:14.104 LoginScreen[29076:4688502] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController setXAuthToken:]: unrecognized selector sent to instance 0x7bfd1140'

ViewController.h

#import <UIKit/UIKit.h>
#import "MainController.h"

@interface ViewController : UIViewController <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *txtUsername;
@property (weak, nonatomic) IBOutlet UITextField *txtPassword;

- (IBAction)sigininClicked:(id)sender;

- (IBAction)backgroundTap:(id)sender;
@end

ViewController.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)sigininClicked:(id)sender {
    NSInteger success = 0;
    @try {

        if([[self.txtUsername text] isEqualToString:@""] || [[self.txtPassword text] isEqualToString:@""] ) {

            [self alertStatus:@"Please enter Email and Password" :@"Sign in Failed!" :0];

        } else {
            NSString *post =[[NSString alloc] initWithFormat:@"username=%@&password=%@",[self.txtUsername text],[self.txtPassword text]];
            NSLog(@"PostData: %@",post);

            NSURL *url=[NSURL URLWithString:@"http://www.mywebsite.com/auth"];

            NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

            NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

            NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
            [request setURL:url];
            [request setHTTPMethod:@"POST"];
            [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
            [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
            [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
            [request setHTTPBody:postData];

            //[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];

            NSError *error = [[NSError alloc] init];
            NSHTTPURLResponse *response = nil;
            NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

            NSLog(@"Response code: %ld", (long)[response statusCode]);

            if ([response statusCode] >= 200 && [response statusCode] < 300)
            {
                NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
                NSLog(@"Response ==> %@", responseData);

                NSError *error = nil;
                NSDictionary *jsonData = [NSJSONSerialization
                                          JSONObjectWithData:urlData
                                          options:NSJSONReadingMutableContainers
                                          error:&error];

                success = [jsonData[@"success"] integerValue];
                NSLog(@"Success: %ld",(long)success);

                if(success == 1)
                {
                    NSLog(@"Login SUCCESS");
                } else {

                    NSString *error_msg = (NSString *) jsonData[@"error_message"];
                    [self alertStatus:error_msg :@"Sign in Failed!" :0];
                }

            } else {
                //if (error) NSLog(@"Error: %@", error);
                [self alertStatus:@"Connection Failed" :@"Sign in Failed!" :0];
            }
        }
    }
    @catch (NSException * e) {
        NSLog(@"Exception: %@", e);
        [self alertStatus:@"Sign in Failed." :@"Error!" :0];
    }
    if (success) {

        [self performSegueWithIdentifier:@"login_success" sender:self];
    }
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"login_success"]) {
        MainController *controller = (MainController *)segue.destinationViewController;
        controller.xAuthToken = @"test string";
    }
}

- (void) alertStatus:(NSString *)msg :(NSString *)title :(int) tag
{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
                                                        message:msg
                                                       delegate:self
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil, nil];
    alertView.tag = tag;
    [alertView show];
}

- (IBAction)backgroundTap:(id)sender {
    [self.view endEditing:YES];
}

-(BOOL) textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}

@end

MainController.h

#import <Foundation/Foundation.h>

@interface MainController : UIViewController

@property (nonatomic,strong) NSString *xAuthToken;

@end

MainController.m

#import "MainController.h"

@interface MainController ()

@end

@implementation MainController

- (void)viewDidLoad
{
    NSLog(@"%@",_xAuthToken);
}

@end
user4114789
  • 9
  • 1
  • 6
  • [This](http://stackoverflow.com/a/8597092/683917) answer can help you. – ifau Oct 11 '14 at 11:36
  • at which line does it crash? – Tuan Oct 11 '14 at 12:02
  • So, how do you know it's crashing? (Is there a message? A stack trace?) Do you have an exception breakpoint enabled? – Hot Licks Oct 11 '14 at 12:18
  • @HotLicks, I edited the question accordingly. Sorry for not including that information before. – user4114789 Oct 11 '14 at 12:33
  • Google "unrecognized selector". (And why did you say it crashes "with unknown error" when the error message is quite explicit?) – Hot Licks Oct 11 '14 at 12:37
  • (And below that exception message is a stack trace. It tells you where the error occurred.) – Hot Licks Oct 11 '14 at 12:40
  • A question about a crash (in *any* language) should include the exact error/exception message and the exception stack trace (if present). A question lacking this info can be (and should be) closed without any further responses. – Hot Licks Oct 11 '14 at 12:43

1 Answers1

0

The stack trace tells you what the problem is - you are trying to set the XAuthToken property on a UINavigationController - but a UINavigationController doesn't have that property.

Your MainController instance is embedded in a UINavigationController, so that is what you get from destinationViewController in prepareForSegue.

You need to access the view controller stack -

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"login_success"]) {
        UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
        MainController *controller = (MainController *)navController.topViewController
        controller.xAuthToken = @"test string";
    }
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Thanks, I'm getting closer. I need to set it to a value I'm getting in `- (IBAction)sigininClicked:(id)sender {}`. So something along the lines of `controller.xAuthToken = [jsonData[@"success"] integerValue];` Is that possible? – user4114789 Oct 11 '14 at 13:14
  • Yes, you just need to save the value into a property in `signingClicked` so that you can access it in `prepareForSegue` – Paulw11 Oct 11 '14 at 19:36