iphone - NSOperationQueue and ASIHTTPRequest -
i'm writing test cases wrapper class written around asihttprequest. reasons can't determine, test cases complete failure before asihttprequest finishes.
here's how program flow works.
- start in test case.
- init http engine object, instruct create new list
- create new asihttprequest object , set up.
- add request operation queue.
- wait until queue empty
- check see if delegate methods called , fail test if weren't.
now, of time works fine , test passes, of time fails because delegate methods called after operation queue returned control wait method.
test case
// set flags 'no' - (void)setup { requestdidfinish = no; requestdidfail = no; } - (void)testcreatelist { nsstring *testlist = @"{\"title\": \"this list\"}"; jkengine *engine = [[jkengine alloc] initwithdelegate:self]; nsstring *requestidentifier = [engine createlist:jsonstring]; [self waituntilenginedone:engine]; nsstring *responsestring = responsestring_; [engine release]; ghassertnotnil(requestidentifier, nil); ghasserttrue(requestdidfinish, nil); ghasserttrue([responsestring hasprefix:@"{\"createoreditlistresult\""], nil); } // puts test holding pattern until http request done - (void)waituntilenginedone:(jkengine *)engine { [engine waituntilfinishedrunning]; } // delegate method called on successful completion - (void)requestfinished:(nsstring *)requestidentifier withresponse:(nsstring *)response { nslog(@"request did finish"); requestdidfinish = yes; responseidentifier_ = [requestidentifier retain]; responsestring_ = [response retain]; }
engine code
- (nsstring *)createlist:(nsstring *)list { asihttprequest *request = [[asihttprequest alloc] initwithurl:[nsurl urlwithstring:url]]; [request addrequestheader:@"content-type" value:kcontenttype]; [request setrequestmethod:kpost]; request.delegate = self; [request appendpostdata:[list datausingencoding:nsutf8stringencoding]]; nsstring *requestidentifier = [nsstring stringwithnewuuid]; [operationqueue_ addoperation:request]; [operationdictionary_ setobject:request forkey:requestidentifier]; return requestidentifier; } // asihttprequest delegate method that's called on success // isn't called until after operationqueue finishes running - (void)requestfinished:(asihttprequest *)request { dlog([request responsestring]); bool cannotifiydelegate = [self.delegate respondstoselector:@selector(requestfinished:withresponse:)]; if (cannotifiydelegate) { nsarray *keyarray = [operationdictionary_ allkeysforobject:request]; nsstring *requestidentifier = [keyarray objectatindex:0]; [operationdictionary_ removeobjectforkey:requestidentifier]; if ([keyarray count] != 1) { alog(@"it looks request added operation dictionary multiple times. there's bug somewhere.", nil); } [self.delegate requestfinished:requestidentifier withresponse:[request responsestring]]; } } - (void)waituntilfinishedrunning { [operationqueue_ waituntilalloperationsarefinished]; }
this way asihttprequest works. delegate methods called on main thread, , calls delegates not block request thread, it's possible delegates called after queue finishes.
Comments
Post a Comment