How can I cancel an asynchronous call through NSURLConnection sendAsynchronousRequest?

痞子三分冷 提交于 2019-11-26 16:58:02

问题


I've got a web service call performing some validation on user input in real time. I'd like to use [NSURLConnection sendAsynchronousRequest] on the validation (which was introduced in iOS 5), but cancel it if the user changes the input field content in the mean time. What is the best way to cancel a current request?


回答1:


It doesn't appear that there is a good way to do this. The solution seems to be to not use the new [NSURLConnection sendAsynchronousRequest] in situations in which you need to cancel the request.




回答2:


I've managed to do this by placing the sendAsynchronousRequest method in a separate DownloadWrapper class, as follows:

//
//  DownloadWrapper.h
//
//  Created by Ahmed Khalaf on 16/12/11.
//  Copyright (c) 2011 arkuana. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol DownloadWrapperDelegate
- (void)receivedData:(NSData *)data;
- (void)emptyReply;
- (void)timedOut;
- (void)downloadError:(NSError *)error;
@end

@interface DownloadWrapper : NSObject {
    id<DownloadWrapperDelegate> delegate;
}
@property(nonatomic, retain) id<DownloadWrapperDelegate> delegate;
- (void)downloadContentsOfURL:(NSString *)urlString;
@end

@implementation DownloadWrapper
@synthesize delegate;

- (void)downloadContentsOfURL:(NSString *)urlString
{
    NSURL *url = [NSURL URLWithString:urlString];

    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:TIMEOUT_INTERVAL];
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
    {
        if ([data length] > 0 && error == nil)
            [delegate receivedData:data];
        else if ([data length] == 0 && error == nil)
            [delegate emptyReply];
        else if (error != nil && error.code == ERROR_CODE_TIMEOUT)
            [delegate timedOut];
        else if (error != nil)
            [delegate downloadError:error];
    }];
}
@end

To utilise this class, I do the following, in addition to declaring the DownloadWrapper *downloadWrapper variable (in the interface declaration) and implementing the protocol methods which handles the response or a lack of one:

NSString *urlString = @"http://yoursite.com/page/to/download.html";
downloadWrapper = [DownloadWrapper alloc];
downloadWrapper.delegate = self;
[downloadWrapper downloadContentsOfURL:urlString];

Then I simply do the following to 'cancel' the connection when the view is about to disappear:

- (void)viewDidUnload
{
    [super viewDidUnload];
    downloadWrapper = nil;
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [downloadWrapper setDelegate:nil];
}

It's as simple as that. This would hopefully mimic the documented cancel method, which states that it does the following:

Once this method is called, the receiver’s delegate will no longer receive any messages for this NSURLConnection.

I was concerned that this (somewhat naive) method means that the packets of data would still come through in response to our URL request - only that we're no longer 'listening in' as the delegate. But then I realised that once the URL request was sent through, there's really no way of stopping the response from coming back to us - we can only disregard it (if not at this level, then still at some lower level in the network hierarchy). Please correct me if I'm wrong.

Either way, hope this helps.



来源:https://stackoverflow.com/questions/8072893/how-can-i-cancel-an-asynchronous-call-through-nsurlconnection-sendasynchronousre

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!