【问题标题】:Cocoa URL APIs: how can I return an error from the server *and* still download the data requested?Cocoa URL API:如何从服务器返回错误*并且*仍然下载请求的数据?
【发布时间】:2012-05-26 05:49:35
【问题描述】:

有趣的编程难题...

我未能将错误初始化为零,所以下面的代码崩溃了。

    NSString *query = [NSString stringWithFormat:@"http://mysite.com/getlatest.php?a=%@", aSuiteName];
    NSURL *url = [NSURL URLWithString:query];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageNotAllowed timeoutInterval:10];
    [request setHTTPMethod:@"GET"];
    NSURLResponse *response = nil;
    NSError *error;
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    if ( !data || error != nil ) {
        NSLog(@"Error downlading %@", error); //CRASH
        return NO;
    }

我的问题是,我怎样才能让我的服务器返回一个错误,使 sendSynchronousRequest:returningResponse:error: 实际上收到一个错误,但仍然继续下载数据?某种非致命错误会导致错误被初始化为 NSError 对象?

这与一个类似的难题有关,我之前希望返回状态信息而不会完全失败。所以,虽然晦涩难懂,但我很想知道是否有这种技术。

虽然这是一个 Cocoa 问题,但我认为答案将在 php.ini 中。类似的东西

<?php

    header( set 503 error here );

    return data;

?>

【问题讨论】:

  • 每个 HTTP 响应都有一个状态码——因此该协议当然支持发送 503 和响应数据。 (我正在将它与我正在开发的 Cocoa 应用程序一起使用。)您是否需要知道如何使用 NSURLRequest 来处理它,或者如何使用 PHP 来生成它?
  • 我回复了下面的Cocoa部分。
  • 我需要知道如何处理 php(或其他一些服务器设置,我不确定它是在 php 代码中还是在控制面板中)。我现在看到 php 是要走的路,设置一个 header()。

标签: php cocoa nsurlconnection nsurl


【解决方案1】:

我通过将数据包装到一个 NSError 对象中来处理这个问题。在纯文本响应的情况下,我还将响应用作本地化描述。我使用单独的方法来评估结果是否成功。如果 URL 请求本身产生错误,我也认为是失败,并传递 URL 请求提供的 NSError。

这是从我的 ServerRequest 类中截取的:

+ (NSError *) errorForStatusCode:(NSInteger) statusCode
                     contentType:(NSString *) contentType
                textEncodingName:(NSString *) textEncodingName
                            data:(NSData *) data {

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    if ([contentType isEqualToString:@"text/plain"]) {
        [userInfo setValue:[[NSString alloc] initWithData:data encoding:[self stringEncodingForTextEncodingName:textEncodingName]]
                    forKey:NSLocalizedDescriptionKey];
    } else if ( ... ) {
        // handle other relevant types         
    }

    return [NSError errorWithDomain:[[self class] description]
                               code:statusCode
                           userInfo:userInfo];
}

- (BOOL) statusCodeIndicatesSuccess:(NSInteger) statusCodeValue {
    return 201 == statusCodeValue; // Modify this based on your API
}

- (BOOL) runSynchronouslyReturningResult:(NSData **) resultPtr error:(NSError **) errorPtr {
    NSHTTPURLResponse *response = nil;
    NSError *error = nil;
    NSData *result = [NSURLConnection sendSynchronousRequest:[self request] returningResponse:&response error:&error];
    if (error) {
        if (errorPtr) *errorPtr = error;
        return NO;
    }

    self.statusCode = [response statusCode];
    self.MIMEType = [response MIMEType];
    self.textEncodingName = [response textEncodingName];
    if ([self statusCodeIndicatesSuccess:self.statusCode]) {
        if (resultPtr) *resultPtr = result;
        return YES;
    } else {
        if (errorPtr) *errorPtr = [ServerRequest errorForStatusCode:self.statusCode
                                                        contentType:self.MIMEType
                                                   textEncodingName:self.textEncodingName
                                                               data:result];
        if (resultPtr) *resultPtr = result;
        return NO;
    }
}

【讨论】:

  • 但是如果你可以更改 Cocoa 代码,为什么不直接解决初始化失败/过度检查error 的原始问题呢?
  • 我无法更改代码。出于所有意图和目的,它正在月球着陆器上运行。所以现在我 - 从一百万英里外 - 改变服务器行为以避免崩溃。不幸的是,该方法仍然会返回“NO”,但至少不会导致应用崩溃。
  • 我不知道您不能更改 Cocoa 代码。您确实粘贴了您知道会因易于修复的错误而损坏的代码,现在我明白了。
  • 这是一个关于 PHP 代码的答案:stackoverflow.com/questions/6163970/set-response-status-code/…
  • 嘿,感谢您提供了非常强大的正确可可答案,我现在可能会将其集成到我的框架中。你的两个答案都是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
  • 2015-11-08
  • 1970-01-01
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
相关资源
最近更新 更多