0

I am making a login application follow http://dipinkrishna.com/blog/2013/12/ios-login-screen-tutorial-xcode-5-ios-7-storyboard-json/.

When I test the APP on iPhone. Everything works great.

But when I test on iPad the APP crash when

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

Here is the crash log:

2014-05-06 19:37:23.662 We Love HK[50458:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present a Split View Controllers modally <LoginViewController: 0x10934f960>.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001019fc495 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010175b99e objc_exception_throw + 43
    2   UIKit                               0x0000000100408c93 -[UIViewController presentViewController:withTransition:completion:] + 4027
    3   We Love HK                          0x0000000100005a2d -[LoginViewController loginClicker:] + 3805
    4   UIKit                               0x0000000100309f06 -[UIApplication sendAction:to:from:forEvent:] + 80
    5   UIKit                               0x0000000100309eb4 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 17
    6   UIKit                               0x00000001003e6880 -[UIControl _sendActionsForEvents:withEvent:] + 203
    7   UIKit                               0x00000001003e595d -[UIControl touchesBegan:withEvent:] + 219
    8   UIKit                               0x0000000100340b74 -[UIWindow _sendTouchesForEvent:] + 300
    9   UIKit                               0x00000001003416e4 -[UIWindow sendEvent:] + 925
    10  UIKit                               0x000000010031929a -[UIApplication sendEvent:] + 211
    11  UIKit                               0x0000000100306aed _UIApplicationHandleEventQueue + 9579
    12  CoreFoundation                      0x000000010198bd21 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    13  CoreFoundation                      0x000000010198b5f2 __CFRunLoopDoSources0 + 242
    14  CoreFoundation                      0x00000001019a746f __CFRunLoopRun + 767
    15  CoreFoundation                      0x00000001019a6d83 CFRunLoopRunSpecific + 467
    16  GraphicsServices                    0x0000000103b29f04 GSEventRunModal + 161
    17  UIKit                               0x0000000100308e33 UIApplicationMain + 1010
    18  We Love HK                          0x00000001000045b3 main + 115
    19  libdyld.dylib                       0x000000010207f5fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

And LoginViewController.h:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "KeychainItemWrapper.h"

@import Security;

@interface LoginViewController : UIViewController <UITextFieldDelegate>

@property (nonatomic, retain) IBOutlet UILabel *version_label;

@property (strong, nonatomic) IBOutlet UITextField *txtUsername;
@property (strong, nonatomic) IBOutlet UITextField *txtPassword;


- (IBAction) loginClicker:(id)sender;
- (IBAction) backgroundTap:(id)sender;
- (IBAction) keyboardDismiss: (id) sender;
- (IBAction) click_exit: (id)  sender;

@end

LoginViewController.m:

#import "LoginViewController.h"

@implementation LoginViewController;

@synthesize version_label;
@synthesize txtUsername;
@synthesize txtPassword;

-(void)viewDidLoad
{
    KeychainItemWrapper *keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"UserAuthToken" accessGroup:nil];
    NSString *version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];  // Get App Version
    NSString *build = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];  // Get App Build Number
    version_label.numberOfLines = 0;                               // Enable \n break line
    version_label.hidden = NO;                                     // Disable Hidden
    //[keychainWrapper resetKeychainItem];
    version_label.text = [NSString stringWithFormat:@"V %@ (Build %@)", version, build];    // Change Version Label's Content
     if ([keychainWrapper objectForKey:(__bridge id)(kSecAttrAccount)] && [keychainWrapper objectForKey:(__bridge id)(kSecValueData)]){
        txtUsername.text = [keychainWrapper objectForKey:(__bridge id)(kSecAttrAccount)];
        txtPassword.text = [keychainWrapper objectForKey:(__bridge id)(kSecValueData)];
    }
}

-(IBAction) keyboardDismiss: (id) sender{
    [txtUsername resignFirstResponder];
    [txtPassword resignFirstResponder];
}

- (IBAction)backgroundTap:(id)sender {
    [txtUsername resignFirstResponder];
    [txtPassword resignFirstResponder];
}

- (IBAction)click_exit:(id)sender {
    //[txtUsername resignFirstResponder];
    //[txtPassword resignFirstResponder];
}

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

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

            [self alertStatus:@"請輸入帳號及密碼!" :@"登入失敗!" :0];

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

            NSURL *url=[NSURL URLWithString:@"http://ls.arefly.com/other/php/welovehk/login.php"];

            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[@"login_status"] integerValue];
                NSLog(@"Success: %ld", (long)success);

                if(success == 1)
                {
                    NSLog(@"Login SUCCESS");
                    [keychainWrapper setObject:[self.txtUsername text] forKey:(__bridge id)(kSecAttrAccount)];
                    [keychainWrapper setObject:[self.txtPassword text] forKey:(__bridge id)(kSecValueData)];
                    NSString *name_msg = (NSString *) jsonData[@"name_msg"];
                    [self alertStatus:name_msg :@"歡迎!" :0];
                } else {
                    NSString *error_msg = (NSString *) jsonData[@"error_message"];
                    [self alertStatus:error_msg :@"登入失敗!" :0];
                    txtPassword.text = @"";
                }

            } else {
                //if (error) NSLog(@"Error: %@", error);
                [self alertStatus:@"Connection Failed" :@"登入失敗!" :0];
                txtPassword.text = @"";
            }
        }
    }
    @catch (NSException * e) {
        NSLog(@"Exception: %@", e);
        [self alertStatus:@"登入失敗!" :@"錯誤:" :0];
        txtPassword.text = @"";
    }
    if (success) {
        [self performSegueWithIdentifier:@"login_success" sender:self];
    }

}

- (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];
}

@end

and here also didFinishLaunchingWithOptions in AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    return YES;
}

and here is my Main_iPad.storyboard:

uploadpie.com/rTIVc

and here is my Main_iPhone.storyboard:

uploadpie.com/gmpms

Can any one help me?

Thanks!

UPDATE

If i change Model to Push in the storyboard, the APP still crash, but it is a different log:

2014-05-06 19:59:32.972 We Love HK[51824:60b] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'login_success'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001019fc495 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x000000010175b99e objc_exception_throw + 43
    2   UIKit                               0x00000001007d1865 -[UIStoryboardPushSegue destinationContainmentContext] + 0
    3   We Love HK                          0x0000000100005a35 -[LoginViewController loginClicker:] + 3813
    4   UIKit                               0x0000000100309f06 -[UIApplication sendAction:to:from:forEvent:] + 80
    5   UIKit                               0x0000000100309eb4 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 17
    6   UIKit                               0x00000001003e6880 -[UIControl _sendActionsForEvents:withEvent:] + 203
    7   UIKit                               0x00000001003e595d -[UIControl touchesBegan:withEvent:] + 219
    8   UIKit                               0x0000000100340b74 -[UIWindow _sendTouchesForEvent:] + 300
    9   UIKit                               0x00000001003416e4 -[UIWindow sendEvent:] + 925
    10  UIKit                               0x000000010031929a -[UIApplication sendEvent:] + 211
    11  UIKit                               0x0000000100306aed _UIApplicationHandleEventQueue + 9579
    12  CoreFoundation                      0x000000010198bd21 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    13  CoreFoundation                      0x000000010198b5f2 __CFRunLoopDoSources0 + 242
    14  CoreFoundation                      0x00000001019a746f __CFRunLoopRun + 767
    15  CoreFoundation                      0x00000001019a6d83 CFRunLoopRunSpecific + 467
    16  GraphicsServices                    0x0000000103b29f04 GSEventRunModal + 161
    17  UIKit                               0x0000000100308e33 UIApplicationMain + 1010
    18  We Love HK                          0x00000001000045b3 main + 115
    19  libdyld.dylib                       0x000000010207f5fd start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 
He Yifei 何一非
  • 2,592
  • 4
  • 38
  • 69

3 Answers3

1

Your segue is modal. Change its mode to push or whatever is more appropriate.

Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • i've try to change it to push and add ID to it. But it still crash – He Yifei 何一非 May 06 '14 at 11:55
  • Now you don't have a navigation controller. Pushing only works with navigation controllers. – Hermann Klecker May 06 '14 at 12:03
  • Are you sure you want to push/present a split view controller at all? Why? What are you trying to achieve? – Hermann Klecker May 06 '14 at 12:04
  • this is a login page and if login success will go to the Master Detail page. – He Yifei 何一非 May 06 '14 at 12:11
  • Well, then get rid of the login page and present the split view instead (by exchanging the root view controller) or have the split view in the background and present the login on top. I would go for the second. The login page may cover the full screen. – Hermann Klecker May 06 '14 at 12:16
  • So can you teach me how to popup the login view on the top? Really Thanks! – He Yifei 何一非 May 06 '14 at 12:19
  • Hmm... just out of the top of my head: In viewDidAppear of the split view controller you could call presentViewController:animated:completion: but only then when the user is not logged in. viewDidAppear will be called again after the user logged in and the login page was dismissed. You could try presenting it from viewDidLoad though. But look out for warnings on the debug console. – Hermann Klecker May 06 '14 at 12:25
0

Change the style of StoryBoard segue which u used to push from "Modal" to "Push".

ratnesh
  • 31
  • 4
  • i've try to change it to push and add Identifier login_success to it. But it still crash – He Yifei 何一非 May 06 '14 at 11:57
  • You should have a navigation controller to push a view controller, so add a navigation controller at the starting of your storyboard & make its rootViewController the first view controller which you want to load. You can do this in the storyboard itself. – ratnesh May 06 '14 at 12:31
  • and one more thing is dat, success is an integer value, so better you check the condition if(success==1) { //push} else{ //error } – ratnesh May 06 '14 at 12:37
0

I got similar problem and struggled a while.

It was turned out that I deleted "Main.storyboard" file from the Copy Bundle Resources accidentally.

Just in case, make sure your "Main.storyboard" file is in the bundle list.

enter image description here

허광호
  • 71
  • 1
  • 3