从Web服务器响应失败后,应用程序崩溃

时间:2013-07-19 15:20:02

标签: ios objective-c nsdata

我有以下代码从我的iOS应用程序登录到Web服务器。虽然显示“登录失败”警报,但应用程序正确登录。此外,如果输入了错误的用户名/密码,则应用程序崩溃。

我不确定错误处理是否错误或语法错误。

崩溃时控制台输出(输入的用户名/通道不正确),响应代码为500:

    PostData: username=ghh&password=hhhh
2013-07-19 16:10:18.477 appName [11414:907] Response code: 500

这里是登录成功的输出(用户名/传递是正确的),响应码:200:

    PostData: username=user-2&password=user-2
2013-07-19 16:15:28.757 appName [11430:907] Response code: 200
2013-07-19 16:15:28.758 appName [11430:907] Response ==> {"meta":[],"data":{"token":"JXVJdC05X0t9NnNqR1RBOzYkbFhUbk91KClRTH11fGk3MmVRcjZEaSVSO3hhemJ5WTQ2OFp5U2htZDtzc01tdHMkTCVGbi18JG4pMXlGITUpezZqSnJWR2dVMmQpWTh5c2h3RTVdVHgodUNdZFIpRTFjIWxKUXVJcnRnLXF0OUo="}}
2013-07-19 16:15:28.764 appName 11430:907] {
    data =     {
        token = "JXVJdC05X0t9NnNqR1RBOzYkbFhUbk91KClRTH11fGk3MmVRcjZEaSVSO3hhemJ5WTQ2OFp5U2htZDtzc01tdHMkTCVGbi18JG4pMXlGITUpezZqSnJWR2dVMmQpWTh5c2h3RTVdVHgodUNdZFIpRTFjIWxKUXVJcnRnLXF0OUo=";
    };
    meta =     (
    );

这是登录方法:

- (IBAction)loginClicked:(id)sender {
    @try {

        if([[txtUsername text] isEqualToString:@""] || [[txtPassword text] isEqualToString:@""] ) {
            [self alertStatus:@"Please enter both Username and Password" :@"Login Failed!"];
        } else {
            NSString *post =[[NSString alloc] initWithFormat:@"username=%@&password=%@",[txtUsername text],[txtPassword text]];
            NSLog(@"PostData: %@",post);

            NSURL *url=[NSURL URLWithString:@"http://*******.net/api/token"];

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

            NSString *postLength = [NSString stringWithFormat:@"%d", [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: %d", [response statusCode]);
            if ([response statusCode] >=200 && [response statusCode] <300)
            {
                NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
                NSLog(@"Response ==> %@", responseData);

                // extract token from json
                NSError *error = nil;
                NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:urlData options:0 error:&error];
                NSString *token = [[responseDict objectForKey:@"data"] objectForKey:@"token"];

                // save token string to nsuserdefaults
                NSString *valueToSave = token;
                [[NSUserDefaults standardUserDefaults]
                 setObject:valueToSave forKey:@"token"];

                SBJsonParser *jsonParser = [SBJsonParser new];
                NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
                NSLog(@"%@",jsonData);
                NSInteger success = [(NSNumber *) [jsonData objectForKey:@"success"] integerValue];
                NSLog(@"%d",success);
                if(success == 1)
                {
                    NSLog(@"Login SUCCESS");
                    [self alertStatus:@"Logged in Successfully." :@"Login Success!"];

                } else {

                    NSString *error_msg = (NSString *) [jsonData objectForKey:@"error_message"];
                    [self alertStatus:error_msg :@"Login Failed!"];

                }

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

不确定这是否有帮助,但这是一些错误输出。第5行是它被捕获的地方 - “陷阱”:

CoreFoundation`CFHash:
0x32119530:  push   {r4, r7, lr}
0x32119532:  mov    r4, r0
0x32119534:  add    r7, sp, #4
0x32119536:  cbnz   r4, 0x32119544            ; CFHash + 20
**0x32119538:  trap**   
0x3211953a:  blx    0x32217a7c                ; symbol stub for: -[NSOrderedSet intersectsSet:]
0x3211953e:  movs   r1, #9
0x32119540:  blx    0x32217b4c                ; symbol stub for: __61-[NSOrderedSet sortedArrayFromRange:options:usingComparator:]_block_invoke_0
0x32119544:  ldrd   r2, r3, [r4]
0x32119548:  cmp    r2, #0
0x3211954a:  ubfx   r0, r3, #8, #10
0x3211954e:  beq    0x32119572                ; CFHash + 66
0x32119550:  movw   r1, #61284
0x32119554:  movt   r1, #2114
0x32119558:  add    r1, pc
0x3211955a:  ldr    r1, [r1]
0x3211955c:  cmp    r2, r1
0x3211955e:  beq    0x32119572                ; CFHash + 66
0x32119560:  movw   r1, #57172
0x32119564:  movt   r1, #2114
0x32119568:  add    r1, pc
0x3211956a:  ldr.w  r1, [r1, r0, lsl #2]
0x3211956e:  cmp    r2, r1
0x32119570:  bne    0x32119588                ; CFHash + 88
0x32119572:  movw   r1, #53054
0x32119576:  movt   r1, #2114
0x3211957a:  add    r1, pc
0x3211957c:  ldr.w  r0, [r1, r0, lsl #2]
0x32119580:  ldr    r1, [r0, #24]
0x32119582:  mov    r0, r4
0x32119584:  cbnz   r1, 0x3211959e            ; CFHash + 110
0x32119586:  pop    {r4, r7, pc}
0x32119588:  movw   r0, #2272
0x3211958c:  movt   r0, #2113
0x32119590:  add    r0, pc
0x32119592:  ldr    r1, [r0]
0x32119594:  mov    r0, r4
0x32119596:  pop.w  {r4, r7, lr}
0x3211959a:  b.w    0x32215fbc                ; objc_msgSend$shim
0x3211959e:  pop.w  {r4, r7, lr}
0x321195a2:  bx     r1

感谢您对此的任何帮助:)

1 个答案:

答案 0 :(得分:2)

始终显示“连接失败”警报的原因是,根据您发布的JSON响应,返回的JSON字典中没有关键字“成功”的对象。这意味着objectForKey返回nil,并且在{nil上调用的integerValue返回0。

崩溃的原因是,当登录失败时,将没有令牌(我假设)。因此,token将为零并且将nil传递给-[NSUserDefaults setObject:forKey:] 引发无效的参数异常。

您需要做的是更改代码,如下所示。

            // extract token from json
            NSError *error = nil;
            NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:urlData options:0 error:&error];
            NSString *token = [[responseDict objectForKey:@"data"] objectForKey:@"token"];

            if (token)     // make sure token is not nil
            {
                 // save token string to nsuserdefaults
                 NSString *valueToSave = token;
                 [[NSUserDefaults standardUserDefaults] setObject:valueToSave forKey:@"token"];
            }

            SBJsonParser *jsonParser = [SBJsonParser new];
            NSDictionary *jsonData = (NSDictionary *) [jsonParser objectWithString:responseData error:nil];
            NSLog(@"%@",jsonData);
            NSInteger success = token ? 1 : 0;   // token was sent = login successful
            NSLog(@"%d",success);