5

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

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

@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 定义如下:

@protocol WSResponseProtocol <NSObject>

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

@end

要使用它,视图控制器只需要符合WSResponseProtocol协议即可捕获响应。像这样进行 Web 服务调用:

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

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

4

2 回答 2

22

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

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

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

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

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

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

像这样实现你的选择器:

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

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

这已成为比我预期的更长的答案。让我知道这是否没有意义,我可以尝试澄清。

此致,

于 2009-12-24T18:36:20.280 回答
1

您的代码原样,我认为不会做任何事情-您在初始化后立即释放代理,因此它甚至永远不会运行。

我喜欢使用的一种方法是在 NSOperation 内部进行同步 NSURLConnection 调用,而 NSOperation 又由 NSOperationQueue 管理。我使队列中的对象位于单例中,因此我只需从任何地方访问该实例并告诉它何时需要启动新连接。

于 2009-12-24T21:38:06.010 回答