【问题标题】:How can I cancel an asynchronous call through NSURLConnection sendAsynchronousRequest?如何通过 NSURLConnection sendAsynchronousRequest 取消异步调用?
【发布时间】:2011-12-25 18:02:42
【问题描述】:

我有一个 Web 服务调用实时对用户输入执行一些验证。我想在验证中使用[NSURLConnection sendAsynchronousRequest](在 iOS 5 中引入),但如果用户同时更改输入字段内容,请取消它。取消当前请求的最佳方法是什么?

【问题讨论】:

    标签: iphone objective-c ios ios5 nsurlconnection


    【解决方案1】:

    我已经设法通过将 sendAsynchronousRequest 方法放在单独的 DownloadWrapper 类中来做到这一点,如下所示:

    //
    //  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
    

    为了使用这个类,除了声明DownloadWrapper *downloadWrapper 变量(在接口声明中)和实现处理响应或缺少响应的协议方法之外,我还执行以下操作:

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

    然后,当视图即将消失时,我只需执行以下操作即可“取消”连接:

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

    就这么简单。这有望模仿记录在案的cancel 方法,该方法指出它执行以下操作:

    一旦调用此方法,接收者的委托将不再 接收此 NSURLConnection 的任何消息。

    我担心这种(有点幼稚的)方法意味着数据包仍然会通过响应我们的 URL 请求——只是我们不再作为代理“监听”。但后来我意识到,一旦发送了 URL 请求,就真的无法阻止响应返回给我们——我们只能忽略它(如果不在这个级别,那么仍然在网络层次结构中的某个较低级别) .如果我错了,请纠正我。

    无论如何,希望这会有所帮助。

    【讨论】:

    • 我对这个解决方案的一个问题是你一次只能有一个代表。 sendAsynchronousRequest:queue:completionHandler: 的好处之一是你可以用来自不同对象的大量请求来轰炸它。如果您是包装委托人,但原始请求对象没有...崩溃。当我尝试在全局 APIClient 中使用此方法时,这对我来说是个问题。所以我同意 Micah 的观点,但这对于简单的实现来说是一个可行的解决方案。
    • 你说得对,它太简单了——即使是我需要它。从那以后,我改变了方法并改用了 Nick Lockwood 的 RequestQueue 课程。如果需要,它具有取消所有(并发)请求或特定请求的方法。
    【解决方案2】:

    似乎没有什么好的方法可以做到这一点。解决方案似乎是在需要取消请求的情况下不使用新的[NSURLConnection sendAsynchronousRequest]

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-19
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多