3
votes

I am trying to do a conditional segue. But I get:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel length]: unrecognized selector sent to instance 0x763c8e0'

The design is, when I pressed a button, the app will retrieve some data from the internet using AFNetworking's AFJSONRequestOperation. If the request succeed, it will call another UIViewController from my current UIViewController. I did my conditional start segue using this method and below are my codes:

-(void) login:(NSString*)pinString{    
NSString* urlString = [NSString stringWithFormat:@"%@%@%@", [super.serverResource getURL], [super.serverResource getRequestByKey:@"login"] ,pinString];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];    
AFJSONRequestOperation *operation = [MenuletJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    [self performSegueWithIdentifier:@"login" sender:self];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
    switch([response statusCode]){
        case (403):{
            UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Log in failed"
                                                      message:@"Log in denied, check your PIN."
                                                      delegate:nil cancelButtonTitle:@"OK"
                                                      otherButtonTitles:nil];
            [alert show];
            break;
        }
    }
}];
[operation start];

}

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
SettingViewController *settingVC = (SettingViewController*)[storyboard instantiateViewControllerWithIdentifier:@"SettingViewController"];
[self presentViewController:settingVC animated:YES completion:nil];

}

And I get the exception above after "ViewDidLoad" excuted in SettingViewController. If I don't use conditional segue, and simply ctl drag from the Button to SettingViewController on IB, everything works fine... please give me some suggestion... I am really out of ideas...

Below are my code from SettingViewController:

- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view.
//StringResources* resource = [[StringResources alloc]init];
[self.titleLabel setText:[super.stringResource getStringByKey:@"screen_setting_title"]];
[self.createOrderLabel setText:[super.stringResource getStringByKey:@"screen_setting_create_order_label"]];
[self.refreshMenuLabel setText:[super.stringResource getStringByKey:@"screen_setting_refresh_menu_label"]];
[self.tableNumberLabel setText:[super.stringResource getStringByKey:@"screen_setting_table_number_label"]];

}

Actually, I didn't put much thing in SettingViewController, all I did was programatically setting some label. And I put breakpoint on each setText, and they all executed without error. So the exception must happened after ViewDidLoad...

This is where the error occur:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); //error occur here
    }
}

Solved... Turn out Segue handle everything. All I need to do is setup a generic segue. and once I called [self performSegueWithIdentifier:@"login" sender:self], everything works perfectly. Thank you everyone... (overriding prepareForSegue will only cause a problem...)

4
This is very very confusing. What do you expect to happen here? You are in the middle of a segue, then you interrupt that to present a modal view controller. What is the relationship between the current view controller, the destination view controller, and this third view controller that you are loading from the storyboard?Jeffery Thomas
Sorry I didn't made myself clear. I created a generic segue on IB (because I read somewhere that I can't start another ViewController from nowhere). So my original segue shouldn't do anything. And when I press the button, 1. it should validate the request using AFNetworking. 2. If the response is correct, it call the generic segue using performSegueWithIdentifier. 3. It should call prepareForSegue. 4. It initiate SettingViewController from storyboard and show it on screen... at least that was what I intended to dohook38
Segues always do something. There is a destination view controller. That view controller is getting loaded and transitioned to. If you are manually loading an presenting a view controller, then don't use a segue.Jeffery Thomas
So how should I display another ViewContoller? I've only done things from IB... not sure how to do it programatically...hook38

4 Answers

3
votes

Option 1: Trust the segue

Make sure the segue goes from your current view controller to SettingViewController.

Then you keep -performSegueWithIdentifier:sender:.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
   // load data from current view controller to segue.destinationViewController
}

Option 2: Manually load the modal view controller

Throw away the segue all together and just load the view controller from the storyboard.

AFJSONRequestOperation *operation = [MenuletJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    SettingViewController *settingVC = (SettingViewController*)[storyboard instantiateViewControllerWithIdentifier:@"SettingViewController"];
    // load data from current view controller to settingVC
    [self presentViewController:settingVC animated:YES completion:nil];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
    // Error handler
}];
2
votes

What you want to do, is click and drag from ViewController(white square on orange background icon), this will create generic seque. Then you can call it from code. The in prepareForSegue you can access you destination VC :

  segue.destinationViewController

and load data there or set any properties you want. I do believe this is recommended way to go about this.

0
votes

Since you get the exception in viewDidLoad on the new VC I guess the segue is working correctly and the problem is in the new VC implementation.

Seeing the error, are you using a NSString comparison like isEqualToString on an UILabel object directly instead of its text property?

Uhm.. if you post some code of the SettingViewController referring to that UILabel causing the crash we could help you out.

0
votes

Today I also encountered this error. I don't know what caused it, I think it's an Xcode bug. It was removed by deleting the segue and recreating it (by CTRL-dragging it from viewcontroller to viewcontroller).

I love Xcode but sometimes it drives me mad.