当使用委托,需要更好的方式来做到顺序处理 [英] When using delegates, need better way to do sequential processing

查看:105
本文介绍了当使用委托,需要更好的方式来做到顺序处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用NSURLConnection的做出一个Web服务异步调用的类WebServiceCaller。这个类提供的委托财产,当Web服务调用完成后,它调用的委托方法webServiceDoneWithXXX。

I have a class WebServiceCaller that uses NSURLConnection to make asynchronous calls to a web service. The class provides a delegate property and when the web service call is done, it calls a method webServiceDoneWithXXX on the delegate.

有多种Web服务方法可以调用,其中两个是说GetSummary和的GetList。

There are several web service methods that can be called, two of which are say GetSummary and GetList.

使用WebServiceCaller的类最初既需要总结和列表,以便他们这样写的:

The classes that use WebServiceCaller initially need both the summary and list so they are written like this:

-(void)getAllData {
    [webServiceCaller getSummary];
}
-(void)webServiceDoneWithGetSummary {
    [webServiceCaller getList];
}
-(void)webServiceDoneWithGetList {
    ...
}

这工作,但至少有两个问题:

This works but there are at least two problems:


  1. 通话跨委托分裂
    方法,所以很难看到
    一目了然但更高的序列
    重要的是它很难控制或
    修改序列。

  2. 有时候我想打电话只是GetSummary不还的GetList所以我
    那么就得用一个丑陋的类级
    状态变量,告诉
    webServiceDoneWithGetSummary是否
    打电话的GetList与否。

假设的GetList不能做直到GetSummary完成并返回一些数据,该数据用作输入来的GetList

Assume that GetList cannot be done until GetSummary completes and returns some data which is used as input to GetList.

有没有更好的方式来处理这一点,仍然得到异步调用?

Is there a better way to handle this and still get asynchronous calls?

根据马特·朗的回答更新:

使用通知,而不是一个代表,它看起来像我可以根据我是否要在全序列(GetSummary +的GetList)或仅GetSummary设置不同的选择解决问题#2。调用GetSummary当两个观察员将仍然使用相同的通知名称。我会写两种不同的方法来处理,而不是使用一个单一的委托方法(在这里我会需要一些类级别的变量来告诉是否然后调用的GetList)GetSummaryDone。

Using notifications instead of a delegate, it looks like I can solve problem #2 by setting a different selector depending on whether I want the full sequence (GetSummary+GetList) or just GetSummary. Both observers would still use the same notification name when calling GetSummary. I would have to write two separate methods to handle GetSummaryDone instead of using a single delegate method (where I would have needed some class-level variable to tell whether to then call GetList).

-(void)getAllData {
    [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(getSummaryDoneAndCallGetList:) 
                 name:kGetSummaryDidFinish object:nil];
    [webServiceCaller getSummary];
}
-(void)getSummaryDoneAndCallGetList {
    [NSNotificationCenter removeObserver]
    //process summary data

    [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(getListDone:) 
                 name:kGetListDidFinish object:nil];
    [webServiceCaller getList];
}
-(void)getListDone {
    [NSNotificationCenter removeObserver]
    //process list data 
}


-(void)getJustSummaryData {
    [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(getJustSummaryDone:)     //different selector but
                 name:kGetSummaryDidFinish object:nil];  //same notification name
    [webServiceCaller getSummary];
}
-(void)getJustSummaryDone {
    [NSNotificationCenter removeObserver]
    //process summary data
}

我没有实际尝试过这个呢。这似乎比有状态变量和假设性陈述更好,但你必须编写更多的方法。我还没有看到问题1解决方案。

I haven't actually tried this yet. It seems better than having state variables and if-then statements but you have to write more methods. I still don't see a solution for problem 1.

推荐答案

这是真的,你获得Web服务调用的结果是(应该是)异步的,但是,你希望你的通话序列中发生。一种方法是将等待第一个调用第二前完成,并当第一完成后通知。所以,在你的第一个请求的-connectionDidFinishLoading(在你的webServiceCaller,我假设),发布通知回控制器告诉它第一个请求成功完成。是这样的:

It's true that obtaining the results of your web services calls are (and should be) asynchronous, however, you want your calls to happen in a sequence. One way would be to wait for the first one to finish before calling the second and post a notification when the first is done. So, in -connectionDidFinishLoading of your first request (in your webServiceCaller, I'm assuming), post a notification back to your controller telling it that the first request finished successfully. Something like:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [connection release];
    // receivedData is an NSMutableData object we've been appending
    // to in the -didReceiveData delegate. We'll pass it in the
    // notification so we can hand the data off to the next request.
    [[NSNotificationCenter defaultCenter] 
           postNotificationName:kGetSummaryDidFinish object:receivedData];
}

然后,回到你的控制器,注册该通知:

Then, back in your controller, register for that notification:

- (void)viewDidLoad;
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
             selector:@selector(getSummaryDidFinish:) 
                 name:kGetSummaryDidFinish object:nil];
}

- (void) getSummaryDidFinish:(NSNotification*)notification;
{
    // If you needed the downloaded data, we passed it in
    NSData *data = [notification object];

    // Decide here if you want to call getList or not.
    if (someConditionOfDataObjectIsTrue)
        [webServiceCaller getList];
}

如果你有很多等候对方像这样的电话,就可以得到pretty混乱和难以维持,所以有可能是你应该考虑设计模式(不是人能在脑海时刻)。但是,这种方法的工作pretty很适合我。通知帮助它更有意义,你可以调用所有从控制器的请求时,您会收到一些符合条件的通知。

If you have a lot of calls that wait on each other like this, it can get pretty confusing and hard to maintain, so there may be a design pattern you should consider (not that one comes to mind at the moment). However, this method has worked pretty well for me. Notifications help it to make more sense as you can call all of your requests from your controller when you receive a notification that meets some criteria.

希望是有道理的。

这篇关于当使用委托,需要更好的方式来做到顺序处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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