How to pause/stop function until SOAP request is complete
EDIT: The problem i am having is that i am using the TapKu calendar, so i am relying on the provided delegates. Here is the problm:
- (NSArray*) calendarMonthView:(TKCalendarMonthView*)monthView marksFromDate:(NSDate*)startDate toDate:(NSDate*)lastDate{
//SOAP Request has NSURLConnection which runs asychonrous delegate methods.
//SOAP Request will return before the data array has been populated
[self SOAPRequest:startDate];
//i need to do something like this, however the SOAPRequest will return and get stuck into the loop instead of the asychronos delegates firing
//therefore i can never set bGettingData to NO.
int iWait;
while (bGettingData) {
iWait++;
}
return dataArray;
}
Hello,
In the app i am creating, i rely on SOAP requests to retrieve data, parse the XML and populate an array.
The problem i have, is that when i check the array it is empty, because the SOAP request has not completed. How do i stop my code from executing until the SOAP request is complete and resume the code? Can this be done through a callb开发者_运维百科ack or threading?
Thanks
Don't temporarily stop, sleep or wait, instead simply exit/quit/return from the current routine/function/method.
Break your current "stuff" into multiple fragments of code, each fragment in its own method.
Use subsequent method(s) to do whatever comes next, and have that method called by the completion routine of your async network/SOAP request.
Basically, your problem is that you are still thinking in terms of procedural coding. The proper paradigm is to use event driven coding: have the OS call your code, rather than having your code call the OS and waiting.
Yes, start here: http://ondotnet.com/pub/a/dotnet/2005/08/01/async_webservices.html
You want indeed to wait for the answer to be complete - a callback is usually easiest. Exactly how depends on the programming library/language you are using (is above in javascript, objectiveC, did you hand code or start with an example).
Check out the answers to Iphone SOAP request step by step tutorial - such as http://macresearch.org/interacting-soap-based-web-services-cocoa-part-1 and http://brismith66.blogspot.com/2010/05/iphone-development-accesing-soap.html. Or follow https://developer.omniture.com/node/321 - which simply waits until the answer has fully arrived.
Unfortunately when using the TapKu calendar, you can not asynchronously load from a database via SOAP. You must synchronously load the calendar, because their is not way to refresh the calendar view once the data has finished loading. If you have 40+ records per month, this will create a huge 5-6 second delay.
This is indeed possible, as an example for the day calendar view, modify _refreshDataPageWithAtIndex to be like this:
- (void) _refreshDataWithPageAtIndex:(NSInteger)index{
UIScrollView *sv = self.pages[index];
TKTimelineView *timeline = [self _timelineAtIndex:index];
CGRect r = CGRectInset(self.horizontalScrollView.bounds, HORIZONTAL_PAD, 0);
r.origin.x = self.horizontalScrollView.frame.size.width * index + HORIZONTAL_PAD;
sv.frame = r;
timeline.startY = VERTICAL_INSET;
for (UIView* view in sv.subviews) {
if ([view isKindOfClass:[TKCalendarDayEventView class]]){
[self.eventGraveYard addObject:view];
[view removeFromSuperview];
}
}
if(self.nowLineView.superview == sv) [self.nowLineView removeFromSuperview];
if([timeline.date isTodayWithTimeZone:self.timeZone]){
NSDate *date = [NSDate date];
NSDateComponents *comp = [date dateComponentsWithTimeZone:self.timeZone];
NSInteger hourStart = comp.hour;
CGFloat hourStartPosition = hourStart * VERTICAL_DIFF + VERTICAL_INSET;
NSInteger minuteStart = round(comp.minute / 5.0) * 5;
CGFloat minuteStartPosition = roundf((CGFloat)minuteStart / 60.0f * VERTICAL_DIFF);
CGRect eventFrame = CGRectMake(self.nowLineView.frame.origin.x, hourStartPosition + minuteStartPosition - 5, NOB_SIZE + self.frame.size.width - LEFT_INSET, NOB_SIZE);
self.nowLineView.frame = eventFrame;
[sv addSubview:self.nowLineView];
}
if(!self.dataSource) return;
timeline.events = [NSMutableArray new];
[self.dataSource calendarDayTimelineView:self eventsForDate:timeline.date andEvents:timeline.events success:^{
[timeline.events sortUsingComparator:^NSComparisonResult(TKCalendarDayEventView *obj1, TKCalendarDayEventView *obj2){
return [obj1.startDate compare:obj2.startDate];
}];
[self _realignEventsAtIndex:index];
if(self.nowLineView.superview == sv)
[sv bringSubviewToFront:self.nowLineView];
}];
}
and then change your eventsForDate function to look like this:
- (void) calendarDayTimelineView:(TKCalendarDayView*)calendarDayTimeline eventsForDate:(NSDate *)eventDate andEvents:(NSMutableArray *)events success:(void (^)())success {
[Model doSomethingAsync andSuccess:^(NSArray *classes) {
// .. Add stuff to events..
success();
}];
}
I'm assuming the pattern for the other controls is very similar. The premise is you're waiting to continue the formatting/layout flow til you get your data.
精彩评论