用于异步 Web 服务调用的 NSURLConnection NSURLRequest 代理 [英] NSURLConnection NSURLRequest proxy for asynchronous web service calls

查看:23
本文介绍了用于异步 Web 服务调用的 NSURLConnection NSURLRequest 代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有多个视图产生相同的 NSURLRequest/NSURLConnection 请求.理想情况下,为了获得一些代码重用,我想要某种代理"来完成创建/执行(异步)请求/连接、设置所有委托方法等的所有底层工作.,所以我不必在每个视图中复制所有那些 NSURLConnection 委托方法处理程序.首先,这种设计方式合理吗?其次,我将如何去做这样的事情?

I have multiple views which make the same NSURLRequest/NSURLConnection request. Ideally, in order to get some code reuse, I'd like to have some sort of a "proxy" which does all the underlying work of creating/executing the (asynchronous) request/connection, setting up all the delegate methods, etc., so I don't have to copy all those NSURLConnection delegate method handlers in each view. First of all, is this design approach reasonable? Second, how would I go about doing something like that?

对于一些背景信息,我尝试了这个并让它工作",但是,它似乎没有异步执行.我创建了一个 Proxy.h/m 文件,其中包含用于不同 Web 服务调用的实例方法(还包含 NSURLConnection 委托方法):

For a little background info, I attempted this and got it to "work", however, it doesn't appear to be executing asynchronously. I created a Proxy.h/m file which has instance methods for the different web service calls (and also contains the NSURLConnection delegate methods):

@interface Proxy : NSObject {

    NSMutableData *responseData;
    id<WSResponseProtocol> delegate;
}

- (void)searchForSomethingAsync:(NSString *)searchString delegate:(id<WSResponseProtocol>)delegateObj;

@property (nonatomic, retain) NSMutableData *responseData;
@property (assign) id<WSResponseProtocol> delegate;

@end

WSResponseProtocol 定义如下:

The WSResponseProtocol is defined as such:

@protocol WSResponseProtocol <NSObject>

@optional
- (void)responseData:(NSData *)data;
- (void)didFailWithError:(NSError *)error;

@end

要使用它,视图控制器只需要遵守 WSResponseProtocol 协议,以捕获响应.进行网络服务调用是这样完成的:

To use this, the view controller simply needs to conform to the WSResponseProtocol protocol, to catch the response(s). Making the web service call is done like so:

Proxy *p = [[Proxy alloc] init];
[p searchForSomethingAsync:searchText delegate:self];
[p release];

我可以提供更多的代码,但其余的可以假设.在调用之前,我开始动画"一个 UIActivityIndi​​catorView 微调器.但旋转器从不旋转.如果我只是将 NSURLConnection 委托方法直接放在视图控制器中,那么微调器就会旋转.所以,这让我觉得我的实现不是异步执行的.这里有任何想法/想法吗?

I can provide more code but the remaining can be assumed. Before calling, I "startAnimating" a UIActivityIndicatorView spinner. But the spinner never spins. If I simply put the NSURLConnection delegate methods directly in the view controller, then the spinner spins. So, it makes me think that my implementation isn't executing asynchronously. Any thoughts/ideas here?

推荐答案

您的方法是合理的,但是,我不确定您为什么要创建自己的协议.这是没有必要的.实现此功能所需的一切都在 Apple 的 文档中在 NSURLConnection 上.如果您从 NSURLConnection 实例化的那个页面获取代码,并使连接成为 ivar 而不是仅仅将其创建为局部变量,那么您可以比较每个回调方法中的连接对象并做出相应的响应.例如,从文档中获取此代码并将连接对象更改为 ivar:

Your approach is reasonable, however, I'm not sure why you are creating your own protocol. This is not necessary. Everything you need to get this implemented is in Apple's documentation on NSURLConnection. If you take the code from that page where the NSURLConnection is instantiated, and make the connection an ivar instead of just creating it as a local variable, you can then compare connection objects in each of the callback methods and respond accordingly. For example, take this code from the docs and change the connection object to an ivar:

// create the request
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"]
                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                    timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
    // Create the NSMutableData that will hold
    // the received data
    // receivedData is declared as a method instance elsewhere
    receivedData=[[NSMutableData data] retain];
} else {
    // inform the user that the download could not be made
}

变量 theConnection 是我们的 ivar.然后你可以像这样检查它:

The variable theConnection is our ivar. Then you can check it like this:

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if (connection == theConnection)
    {
        // do something with the data object.
        [connectionSpecificDataObject appendData:data];
    }
}

您当然可以实现它,按照您的建议创建自己的协议,然后回调符合您协议的委托,但您最好使用成功和失败选择器实例化您的对象,您可以查看.像这样:

You can certainly implement it creating your own protocol as you're suggesting and then call back out to the delegate that conforms to your protocol, but you may be better off just instantiating your object using a success and failure selector that you can check. Something like this:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (connection == theConnection)
    {
        if (delegate && [delegate respondsToSelector:successSelector])
            [delegate performSelector:successSelector 
                           withObject:connectionSpecificDataObject];
    }
    [connection release];
}

其中 dataDidDownloadSelector 是您在创建包含所有这些代码的下载委托时设置的 SEL 实例变量——您的代理对象.像这样:

Where dataDidDownloadSelector is a SEL instance variable that you set when you created your download delegate where all of this code is contained--your Proxy object. Something like this:

Proxy *p = [[Proxy alloc] init];
[p searchForSomethingAsync:searchText 
                  delegate:self 
           successSelector:@selector(didFinishWithData:) 
              failSelector:@selector(didFailWithError:)];

像这样实现你的选择器:

Implement your selectors like this:

- (void)didFinishWithData:(NSData*)data;
{
    // Do something with data
}

- (void)didFailWithError:(NSError*)error
{
    // Do something with error
}

这已成为比我预期更长的答案.如果它没有意义,请告诉我,我可以尝试澄清.

This has become a longer answer than I intended. Let me know if it doesn't make sense and I can try to clarify.

最好的问候,

这篇关于用于异步 Web 服务调用的 NSURLConnection NSURLRequest 代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆