我有一个WebServiceCaller类,它使用NSURLConnection对Web服务进行异步调用。该类提供了一个委托属性,当Web服务调用完成后,它会在委托上调用方法webServiceDoneWithXXX。
可以调用几种Web服务方法,其中两种是GetSummary和GetList。
使用WebServiceCaller的类最初需要摘要和列表,因此它们的编写方式如下:
-(void)getAllData {
[webServiceCaller getSummary];
}
-(void)webServiceDoneWithGetSummary {
[webServiceCaller getList];
}
-(void)webServiceDoneWithGetList {
...
}
这样可行,但至少有两个问题:
假设在GetSummary完成之前无法完成GetList并返回一些用作GetList输入的数据。
有没有更好的方法来处理这个问题,仍然可以进行异步调用?
根据Matt Long的回答进行更新:
使用通知代替委托,看起来我可以通过设置不同的选择器来解决问题#2,具体取决于我是否需要完整序列(GetSummary + GetList)或只是GetSummary。在调用GetSummary时,两个观察者仍将使用相同的通知名称。我必须编写两个单独的方法来处理GetSummaryDone而不是使用单个委托方法(我需要一些类级变量来判断是否要调用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
}
我还没有尝试过这个。它似乎比拥有状态变量和if-then语句更好,但你必须编写更多方法。我仍然没有看到问题1的解决方案。
答案 0 :(得分:1)
确实,获取Web服务调用的结果是(并且应该是)异步的,但是,您希望调用按顺序进行。一种方法是在调用第二个之前等待第一个完成,并在第一个完成时发布通知。所以,你的第一个请求的in -connectionDidFinishLoading(在你的webServiceCaller中,我假设),将通知发回给你的控制器,告诉它第一个请求成功完成。类似的东西:
- (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];
}
然后,回到您的控制器中,注册该通知:
- (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];
}
如果你有很多相互等待的电话,它可能会让人感到困惑和难以维护,所以可能会考虑一种设计模式(目前不会想到这一点)。但是,这种方法对我来说效果很好。通知可以帮助您更有意义,因为当您收到符合某些条件的通知时,您可以从控制器调用所有请求。
希望这是有道理的。