【问题标题】:GCD network requests failing on iOS 4GCD 网络请求在 iOS 4 上失败
【发布时间】:2012-03-22 20:18:25
【问题描述】:

我的应用程序中有以下代码可以从我的 API 加载一些数据。它工作正常,实际上在 iOS 5 中很棒,但在 iOS 4 上,我收到了很多状态为 204 的响应。

这只发生在 iOS 4 上,这可能被视为 API 错误,但它在浏览器、Rested.app、iOS 5 等上运行良好......只有 iOS 4 失败,它在模拟器中失败并在设备上 (iPhone 4)。

每次将单元格加载到表格视图中时,我都会调用此代码。我有一个具有加载状态的核心数据对象,最初设置为 no,如果未加载,我执行此代码,如果已加载,则跳过此代码。同时,我在表格视图的单元格内显示了一个微调器。

我确定这是 iOS 4 上 GCD 中的多个请求的问题。

谁能发现我的代码 sn-p 有什么问题?

-(void)myFunction{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // query users participations (Network)

        NSError * _urlError = nil;
        NSString * url = [NSString stringWithFormat:@"my api url"];
        NSMutableURLRequest * loginHTTPRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
        [loginHTTPRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];

        NSLog(@"Description: %@", [loginHTTPRequest description]);

        NSHTTPURLResponse   * _responseHeaders  = nil;
        NSData              * responseData      = [NSURLConnection sendSynchronousRequest:loginHTTPRequest 
                                                                        returningResponse:&_responseHeaders 
                                                                                    error:&_urlError];
        if(_urlError != nil){
            dispatch_async( dispatch_get_main_queue(), ^{
                // alert network connection error
            });
            return;
        }

        NSString *json_string = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

        SBJsonParser *parser = [[SBJsonParser alloc] init];
        NSDictionary * jsonData = [NSDictionary dictionaryWithDictionary:[parser objectWithString:json_string]];
        [json_string release];
        [parser release];

        dispatch_async( dispatch_get_main_queue(), ^{
            // here [_responseHeaders statusCode] keeps returning 204 and there is nothing in responseData

            // do some Core Data stuff
        });

    });
}

更新

请注意,即使使用 for 循环反复调用此代码也可以正常工作,问题是当我从 tableView:cellForRowAtIndexPath 调用此方法时:

我将 Core Data 对象的属性“isLoaded”设置为 NO,并在远程加载时更改为 YES。当我的 tableview 的数据源为每个对象加载单元格时,如果对象的 "isLoaded" 属性为 NO,tableView:cellForRowAtIndexPath: 方法将调用此函数。

我怀疑问题可能是因为在加载和重新加载表时同时调用了 2 个或更多 API。每次从 api 成功加载都会为该 tableview 调用 reloadData。

这让我有一个带有微调器的预填充表格视图,并在我需要时在屏幕上异步加载我的数据,这很好,因为我可以有效地使用 NSFetchedResultsController 并延迟加载我的对象核心数据。

(我的所有对象都有一个端点,返回一个对象 id 的数组 - 我创建的核心数据对象只有 ID,所有其余的数据、名称、日期等......在需要之前不会加载)。

当我开始滚动创建/重用的新单元格时,调用此方法,它们总是会收到 200 响应数据。这只是导致此“阻塞”的第一次加载。

【问题讨论】:

  • 您是否可以看到任何异常的 iOS 日志语句?根据 w3.org/Protocols/rfc2616/rfc2616-sec10.html,204 响应在 responseData 中不得包含任何内容。你控制它连接的服务器吗?那里有区分的日志吗?
  • 另外 - sendSynchronousRequest 在处理 https 方面确实存在限制,通常您会通过使用委托异步获取更多信息(以复杂性为代价)。这些是http还是https?
  • 嗨,它是 https,不幸的是,我无法控制服务器,似乎如果我从应用程序委托或其他类调用我的函数,它会很好,但不是从我的表格视图在导航控制器中,我正在执行此操作的上下文有些奇怪......

标签: ios4 nsurlconnection grand-central-dispatch


【解决方案1】:

我想我找到了问题,我在异步 GCD 线程上执行同步请求,并且由于某种原因发生超时,但仅在 iOS 4 中的请求上,可能标头的发送方式与 iOS 4 略有不同,这导致API 需要更长的时间来响应?或者,在异步线程上从不同线程同步发送的多个(如同时到毫秒)请求在发送之前在系统中发生冲突?

无论如何...这似乎不是调用 google.com 甚至我自己的私人服务器的情况,所以它必须与标头和多个请求有关...

我正在使用来自 github 的 asi http,它的工作效率更高,现在我没有使用 GCD 来处理这些请求,只是一个 ASI 队列。

对在异步 GCD 线程上执行的 iOS 4 同步请求有什么最终想法,可能超时未得到遵守并以状态 204 提前返回?

【讨论】:

    【解决方案2】:

    好的 - 如果是 https,那么您可能无法使用 sendSynchronousRequest。文档指出像[NSURLConnection connection:didReceiveAuthenticationChallenge:] 这样的东西不会调用一些关键的东西,即:

    如果需要身份验证才能下载请求,则必须将所需凭据指定为 URL 的一部分。如果身份验证失败或缺少凭据,连接将尝试在没有凭据的情况下继续。

    老实说,我仍然对它在 iOS5 上运行感到惊讶。我认为您必须使用异步方法至少对其进行调试以了解发生了什么。

    【讨论】:

    • 我只需要在某些 API 端点上提供基本身份验证,但所有 http 都被重定向到 https,导致问题的一个是没有额外标头的 GET 端点。
    • 如果原因是 iOS4 处理异步期望的方式与 iOS5 不同,则需要转向异步方法来证明这一点。
    • 嗨,感谢您的反馈,我真的不认为这是一个问题,我试图在另一个测试应用程序中重新创建这个问题,但我不能,我也更新了一些问题更多细节,这是一个非常特殊的问题,欢迎任何帮助和想法......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多