【问题标题】:NSURLConnection sendAsynchronousRequest not getting a responseNSURLConnection sendAsynchronousRequest 没有得到响应
【发布时间】:2014-01-28 22:30:26
【问题描述】:

我有一个创建NSURLRequest 的方法,并使用NSURLConnection 方法sendAsynchronousRequest:queue:compltionHandler: 发送该请求。这在我获取 json 文件或图像数据时工作正常,但是当我尝试获取 XML 文档时,发生了一些非常奇怪的事情。该方法正在被调用,但从来没有响应,所以完成处理程序永远不会被调用。有谁知道如何解决这一问题?我已经使用这种方法数百次了,但我从未见过这种行为。这是我调用sendAsynchronousRequest:queue:compltionHandler:的方法

- (void)getCachedFile:(NSString *)title withCompletion:(void (^)(NSData *data))completion
{
    Reachability *reach = [Reachability reachabilityForInternetConnection];
    NetworkStatus status = [reach currentReachabilityStatus];
    if (status == NotReachable)
    {
        // read data locally
        NSError *error = nil;
        NSData *data = [NSData dataWithContentsOfFile:[self filePath:title]
                                              options:NSDataReadingUncached
                                                error:&error];
        if (error)
        {
            NSLog(@"COULD NOT READ LOCAL CACHED DATA: %@", error.localizedDescription);
        }
        else
        {
            completion(data);
        }
    }
    else
    {
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:title]
                                                 cachePolicy:NSURLRequestUseProtocolCachePolicy
                                             timeoutInterval:30.0f];

        // get data from NSURLCache
        NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
        if (cachedResponse)
        {
            // if the data is found in the response, use it
            completion([cachedResponse data]);
        }
        else
        {
            // get the data from the server
            [NSURLConnection sendAsynchronousRequest:request
                                               queue:[NSOperationQueue currentQueue]
                                   completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                                       if (connectionError)
                                       {
                                           NSLog(@"ERROR CONNECTING DATA FROM SERVER: %@", connectionError.localizedDescription);
                                       }
                                       else
                                       {
                                           [self.writingOperationQueue addOperationWithBlock:^{
                                          [[NSFileManager defaultManager] createFileAtPath:[self filePath:title]
                                                                                  contents:data
                                                                                attributes:nil];
                                           }];
                                           completion(data);
                                       }
                                   }];
        }
    }
}

【问题讨论】:

    标签: ios objective-c nsurlconnection nsurlrequest


    【解决方案1】:

    一般注意几点: 您的网络请求完成块正在捕获self。这将导致保留周期。

    ^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if (connectionError)
        {
            NSLog(@"ERROR CONNECTING DATA FROM SERVER: %@", connectionError.localizedDescription);
        } else {
            [self.writingOperationQueue addOperationWithBlock:^{
                [[NSFileManager defaultManager] createFileAtPath:[self filePath:title]
                                                        contents:data
                                                      attributes:nil];
            }];
            completion(data);
        }
    }
    

    要修复它,您应该在块之前声明一个变量__weak MyClass *weakSelf = self;,并且只能在块内使用它。

    您的具体问题可能与您正在调用的文档类型无关,而与您从哪个线程调用它无关。您正在[NSOperationQueue currentQueue] 上执行网络操作。如果这是一个系统队列,它可能会在您的请求完成之前被释放。您应该声明一个 NSOperationQueue 属性并在其上执行所有网络请求。

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

    应改为:

    [NSURLConnection sendAsynchronousRequest:request
                                       queue:self.networkOpQueue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {...}];
    

    【讨论】:

    • 我一般同意,但有两个非常小的观察结果: 1. 在完成块中包含self 在这种情况下不会导致强引用循环。它只在网络运行期间保留self。 2.sendAsynchronousRequest中的queue不是网络操作发生的地方,而是运行完成块的地方。鉴于他正在节省 writingOperationQueue(这很好),他可能只使用 [NSOperationQueue mainQueue],因此 complete 块在主队列上运行(这对于 UI 和模型更新可能很重要)。
    • 您发现这些更改在这种情况下是可以接受的,但并非在所有情况下都可以接受。我想确保它可以被推广,即使其他人使用并滥用它。
    猜你喜欢
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多