iOS7 NSURLConnection sendAsynchronousRequest因POST数据失败

土豆黄

我的问题是在iOS7上采用[NSURLConnection sendAsynchronousRequest...]withPOST方法失败,但在iOS6环境上失败。

其他信息:

  1. 在我的iOS6环境中,可以像这样从Server获取JSON数据。(成功)

    {
        "status": 200,
        "data": [
            {
                "oauth_token": "BVgOa01tg6JvfuXOPoJS8wB26TpvAaDs"
            }
        ]
    }
    
  2. iOS7上的相同代码将收到此错误消息。(失败)

    错误:错误域= NSCocoaErrorDomain代码= 3840“操作无法完成。(可可错误3840。)”(无值。)

  3. 我检查了服务器端的PHP代码,发现服务器可以从iOS6 POST数据中获取数据,但不能从iOS7中获取POST数据。(相同的代码结果不同,很奇怪。)

有没有人可以帮助我或为我提供建议?多谢。

我的代码如下(已更新至v3,成功)(感谢Rob'Answer)

- (void) apiLogin
{
    NSDictionary *params = @{@"client_id"     : @"1234567",
                         @"response_type" : @"token",
                         @"redirect_uri"  : @"/oauth2-php/server/examples/pdo/",
                         @"state"         : @"test_state",
                         @"scope"         : @"",
                         @"accept"        : @"Yep",
                         @"uid"           : uid,
                         @"pwd"           : withPwd};

    NSData *postDataString = [self dataForHTTPPost:params];

    // Server API 位置
    NSURL *url=[NSURL URLWithString:@"http://xxx.xxx.tw/xxx.php"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120];
    [request setURL:url];

    // Solution3:
    NSString *postLength = [NSString stringWithFormat:@"%d", [postDataString length]];
    [request setHTTPMethod:@"POST"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postDataString];

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        NSInteger responseCode = [(NSHTTPURLResponse *)response statusCode];
        NSLog(@"D1: responseCode: %d", responseCode);
        if (!connectionError && responseCode == 200) {
            // 採用Apple官方方法將 來源轉成JSON Format並交由NSDictionary 接手.
            NSError *localError = nil;
            NSLog(@"data:%@", data);
            NSDictionary *allInDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&localError];
            NSLog(@"Source:%@", allInDic);
            NSLog(@"error:%@", localError);

            // 取出oauth_token資料
            if ([[allInDic objectForKey:@"status"] integerValue] == 200) {

                // 將新取得之 oauth_token 寫入DB
                NSArray * dataArray = [allInDic objectForKey:@"data"];
                NSDictionary *responseData = [dataArray objectAtIndex:0];

                NSString *t = [responseData objectForKey:@"oauth_token"];
                [helper setDbOauthToken:nil :t :TABLE_USER_PROFILES];
                NSLog(@"(API-New)oauth_token:%@", t);
            } else
            {
              NSLog(@"connectionError=%@", connectionError);
              NSLog(@"responseCode=%d", responseCode);
            }
        }
    }];
}

- (NSData *)dataForHTTPPost:(NSDictionary*) parms
{
    NSMutableArray *array = [NSMutableArray array];
    for (NSString *key in parms) {
        id obj = [parms objectForKey:key];
        NSString *valueString;

        if ([obj isKindOfClass:[NSString class]])
          valueString = obj;
        else if ([obj isKindOfClass:[NSNumber class]])
          valueString = [(NSNumber *)obj stringValue];
        else if ([obj isKindOfClass:[NSURL class]])
          valueString = [(NSURL *)obj absoluteString];
        else
          valueString = [obj description];

        [array addObject:[NSString stringWithFormat:@"%@=%@", key, valueString]];
    }
    NSString *postString = [array componentsJoinedByString:@"&"];
    NSLog(@"New2a HTTPPost Data:%@", postString);

    return [postString dataUsingEncoding:NSUTF8StringEncoding];
}

- (IBAction)loginAction:(id)sender {

    [self apiLogin];
}

以下代码是iOS6上的调试输出

New2a HTTPPost Data:response_type=token&uid=xxx&accept=Yep&scope=&client_id=1234567&state=test_state&redirect_uri=/oauth2-php/server/examples/pdo/&pwd=xxx
D1: responseCode: 200
data:<7b227374 61747573 223a3230 302c2264 61746122 3a5b7b22 6f617574 685f746f 6b656e22 3a224870 47366546 4b304a37 38434343 54306352 506e4d77 62544d5c 2f455631 32793422 7d5d7d>
Source:{
    data =     (
                {
            "oauth_token" = "HpG6eFK0J78CCCT0cRPnMwbTM/EV12y4";
        }
    );
    status = 200;
}
error:(null)
(API-New)oauth_token:HpG6eFK0J78CCCT0cRPnMwbTM/EV12y4

下面的代码是iOS7上的调试输出

New2a HTTPPost Data:response_type=token&uid=&accept=Yep&scope=&client_id=1234567&state=test_state&redirect_uri=/oauth2-php/server/examples/pdo/&pwd=
D1: responseCode: 200
data:<>
Source:(null)
error:Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (No value.) UserInfo=0x8a28d90 {NSDebugDescription=No value.}
connectionError=(null)
responseCode=200

感谢Rob的大力帮助,“我的问题”已解决。根目录是下面的代码。在IOS6中,当“ idField.txt”字段上没有输入时,我可以获得uid / withPwd默认值。但是在iOS7中,此代码无法使用(uid / withPwd)获得默认值。谢谢罗伯,我的问题解决了。

NSString *uid = idField.text;
NSString *withPwd = pwdField.text;

// For testing Account ID
if (!uid||!withPwd) {
    uid=@"[email protected]";
    withPwd=@"xxxx";
}
NSLog(@"uid:%@ , pwd:%@", uid, withPwd);

将问题代码更新为可以在iOS6和iOS7上正常工作

// For testing Account ID
if ([uid isEqualToString:@""] || [withPwd isEqualToString:@""] ) {
    uid=@"[email protected]";
    withPwd=@"xxxx";
}

您正在记录data,但您可能希望查看它的字符串表示形式。查看结果字符串,并查看服务器响应中的内容。这样,如果您的服务器失败并返回了一些非JSON错误消息,则可以看到字符串是什么。

同样,connectionError如果不是可能要记录nil这里不是这种情况(否则,您可能还没有掌握最新的知识NSLog,但是如果不是的话,值得一看nil)。从而:

if (!connectionError && responseCode == 200) {
    // 採用Apple官方方法將 來源轉成JSON Format並交由NSDictionary 接手.
    if (data)
        NSLog(@"data string: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    else
        NSLog(@"data is nil");

    NSError *parseError = nil;
    NSDictionary *allInDic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&parseError];
    NSLog(@"Source:%@", allInDic);
    NSLog(@"error:%@", parseError);

    // 取出oauth_token資料
    if ([allInDic[@"status"] integerValue] == 200) {

        // 將新取得之 oauth_token 寫入DB
        NSArray * dataArray = allInDic[@"data"];
        NSDictionary *responseDictionary = dataArray[0];

        NSString *t = responseDictionary[@"oauth_token"];
        [helper setDbOauthToken:nil :t :TABLE_USER_PROFILES];
        NSLog(@"(API-New)oauth_token:%@", t);
    }
}
else
{
    NSLog(@"connectionError=%@", connectionError);
    NSLog(@"responseCode=%d", responseCode);
}

我怀疑一旦您查看了您的字符串表示形式data,问题可能就变得不言而喻。


顺便说一句,这不太可能成为问题,但请确保正确编码了要添加到中的字符串postData例如,如果您的密码包含“&”号,加号,空格或其他保留字符(如RFC2396的2.2节所述),则您当前的代码将不起作用。您可能要应用CFURLCreateStringByAddingPercentEscapes添加到的值postData,例如,可以使用如下NSString类别:

@implementation NSString (URLPostEncode)

- (NSString *)stringForHTTPPost
{
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)self,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@";/?:@&=+$,",
                                                                                 kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

@end

我个人将其与以下NSDictionary类别结合

@implementation NSDictionary (URLPostEncode)

- (NSData *)dataForHTTPPost
{
    NSMutableArray *array = [NSMutableArray array];
    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        NSString *valueString;

        if ([obj isKindOfClass:[NSString class]])
            valueString = obj;
        else if ([obj isKindOfClass:[NSNumber class]])
            valueString = [(NSNumber *)obj stringValue];
        else if ([obj isKindOfClass:[NSURL class]])
            valueString = [(NSURL *)obj absoluteString];
        else
            valueString = [obj description];

        [array addObject:[NSString stringWithFormat:@"%@=%@", key, [valueString stringForHTTPPost]]];
    }];

    NSString *postString = [array componentsJoinedByString:@"&"];

    return [postString dataUsingEncoding:NSUTF8StringEncoding];
}

@end

有了这两个类别,我可以执行以下操作:

NSDictionary *params = @{@"client_id"     : client_id,
                         @"response_type" : response_type,
                         @"redirect_uri"  : redirect_uri,
                         @"state"         : state,
                         @"scope"         : scope,
                         @"accept"        : accept,
                         @"uid"           : uid,
                         @"withPwd"       : withPwd};

NSData *postData = [params dataForHTTPPost];

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

iOS NSURLConnection(sendAsynchronousRequest :)缓存过多

来自分类Dev

ios7在弹出视图中的异步nsurlconnection

来自分类Dev

POST请求错误:NSURLConnection HTTP加载失败iOS 10

来自分类Dev

等待直到NSURLConnection sendAsynchronousRequest完成

来自分类Dev

NSURLSession / NSURLConnection HTTP加载在iOS 9上失败

来自分类Dev

iOS NSURLConnection / CFURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9813)

来自分类Dev

iOS NSURLConnection / CFURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9813)

来自分类Dev

在iOS中取消NSURLConnection

来自分类Dev

ios取消NSURLConnection Swift

来自分类Dev

在iOS中取消NSURLConnection

来自分类Dev

ios取消NSURLConnection Swift

来自分类Dev

iOS 中的 NSURLConnection swizzling

来自分类Dev

使用NSURLConnection检索数据

来自分类Dev

如何使用NSURLConnection的sendAsynchronousRequest方法分段接收数据?

来自分类Dev

存折在iOS7上失败,并显示无效数据错误

来自分类Dev

NSURLConnection sendAsynchronousRequest没有得到响应

来自分类Dev

Segue抛出NSInternalInconsistencyException,带有NSURLConnection sendAsynchronousRequest

来自分类Dev

NSURLConnection sendAsynchronousRequest没有得到响应

来自分类Dev

如何取消[NSURLConnection sendAsynchronousRequest:..]发送的请求

来自分类Dev

iOS NSUrlConnection检查上传速度

来自分类Dev

iOS NSURLConnection不调用connectionDidFinishLoading

来自分类Dev

常见的NSURLCONNECTION失败原因

来自分类Dev

在NSURLConnection上返回的JSON数据

来自分类Dev

AVAssetExportSession失败-合并2个WAV文件(iOS7)

来自分类Dev

使用令牌创建的Twitter帐户在iOS7上失败

来自分类Dev

Apache DefaultHttpClient(Android)和NSURLConnection(iOS)是否使用旧协议版本重试失败的连接?

来自分类Dev

在应用关闭时从cancelByProducingResumeData保存数据[iOS7]

来自分类Dev

在sqlite iOS7上创建数据库

来自分类Dev

iCloud无法正确同步核心数据(iOS7)

Related 相关文章

  1. 1

    iOS NSURLConnection(sendAsynchronousRequest :)缓存过多

  2. 2

    ios7在弹出视图中的异步nsurlconnection

  3. 3

    POST请求错误:NSURLConnection HTTP加载失败iOS 10

  4. 4

    等待直到NSURLConnection sendAsynchronousRequest完成

  5. 5

    NSURLSession / NSURLConnection HTTP加载在iOS 9上失败

  6. 6

    iOS NSURLConnection / CFURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9813)

  7. 7

    iOS NSURLConnection / CFURLConnection HTTP加载失败(kCFStreamErrorDomainSSL,-9813)

  8. 8

    在iOS中取消NSURLConnection

  9. 9

    ios取消NSURLConnection Swift

  10. 10

    在iOS中取消NSURLConnection

  11. 11

    ios取消NSURLConnection Swift

  12. 12

    iOS 中的 NSURLConnection swizzling

  13. 13

    使用NSURLConnection检索数据

  14. 14

    如何使用NSURLConnection的sendAsynchronousRequest方法分段接收数据?

  15. 15

    存折在iOS7上失败,并显示无效数据错误

  16. 16

    NSURLConnection sendAsynchronousRequest没有得到响应

  17. 17

    Segue抛出NSInternalInconsistencyException,带有NSURLConnection sendAsynchronousRequest

  18. 18

    NSURLConnection sendAsynchronousRequest没有得到响应

  19. 19

    如何取消[NSURLConnection sendAsynchronousRequest:..]发送的请求

  20. 20

    iOS NSUrlConnection检查上传速度

  21. 21

    iOS NSURLConnection不调用connectionDidFinishLoading

  22. 22

    常见的NSURLCONNECTION失败原因

  23. 23

    在NSURLConnection上返回的JSON数据

  24. 24

    AVAssetExportSession失败-合并2个WAV文件(iOS7)

  25. 25

    使用令牌创建的Twitter帐户在iOS7上失败

  26. 26

    Apache DefaultHttpClient(Android)和NSURLConnection(iOS)是否使用旧协议版本重试失败的连接?

  27. 27

    在应用关闭时从cancelByProducingResumeData保存数据[iOS7]

  28. 28

    在sqlite iOS7上创建数据库

  29. 29

    iCloud无法正确同步核心数据(iOS7)

热门标签

归档