views:

165

answers:

2

I want to make two separate asynchronous internet lookups. However, they are stepping on each other and I'm not sure why.

When I dig around, it appears the two lookups are both operating on the same object (symptom: the second call is resetting "thisPage" set by the first call).

Maybe this has something to do with delegate usage (still not comfortable in this area)?


I've created a class CSNet and I initialize it:

CSNet      *startupPage;
CSNet      *positionUpdatePage;
startupPage = [[CSNet alloc] init];
positionUpdatePage = [[CSNet alloc] init];

Later, I try to use each object:

[startupPage getPage:self page:pageName];

and:

[positionUpdatePage getPage:self page:pageName];

module-level variable:

enum pageType {nothing, startup, positionUpdate, acquireOpponents, fire, changeCredentials};
enum pageType thisPage;

getPage call:

-(void)getPage:(id)delegate page:(NSString *)page {
m_Delegate = delegate;
if ([[page substringToIndex:2] isEqual:@"st"]) {
  thisPage = startup;
} else {
 if ([[page substringToIndex:2] isEqual:@"pu"]) {
  thisPage = positionUpdate;
 } else {
  if ([[page substringToIndex:2] isEqual:@"ao"]) {
   thisPage = acquireOpponents;
  } else {
   if ([[page substringToIndex:2] isEqual:@"fi"]) {
    thisPage = fire;
   } else {
    if ([[page substringToIndex:2] isEqual:@"cc"]) {
     thisPage = changeCredentials;
    } 
   }
  }
 }
} 

NSURLRequest *startupRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[
 [NSString stringWithFormat: @"%@%@", SERVER, page] 
 stringByReplacingOccurrencesOfString:@" " withString:@"%20"]]];
startupConnection = [[NSURLConnection alloc] initWithRequest:startupRequest delegate:self];

if(startupConnection)
{
 workInProgress = YES;
 m_RequestData = [[NSMutableData data] retain];
}
 }

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

// this method is called when the server has determined that it
// has enough information to create the NSURLResponse
// it can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is declared as a method instance elsewhere
[m_RequestData setLength:0];

}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[m_RequestData appendData:data];    
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// release the data object
[m_RequestData release];

// inform the user
NSLog(@"Connection failed! Error - %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
workInProgress = NO;
}

returning back to delegate:

 - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if(workInProgress == YES) {
 workInProgress = NO;
 switch (thisPage) {
  case startup:
   //if ([m_Delegate respondsToSelector:@selector(startupReady:)])
    [m_Delegate startupReady:m_RequestData];
   break;
  case positionUpdate:
   //if ([m_Delegate respondsToSelector:@selector(positionUpdateReady:)])
    [m_Delegate positionUpdateReady:m_RequestData];
   break;
  case acquireOpponents:
   //if ([m_Delegate respondsToSelector:@selector(opponentsReady:)])
    [m_Delegate opponentsReady:m_RequestData];
   break;
  case fire:
   //if ([m_Delegate respondsToSelector:@selector(fireReady:)])
    [m_Delegate fireReady:m_RequestData];
   break;
  case changeCredentials:
   //if ([m_Delegate respondsToSelector:@selector(changeCredentialsReady:)])
    [m_Delegate changeCredentialsReady:m_RequestData];
   break;
  default:
   break;
 }
 [m_RequestData release];
} 
}
+2  A: 

You can keep track of which object is sending methods to the delegate, and handle the two connections distinctly in the same delegate object. If you look at the method signature for delegate methods such as -connection:didReceiveResponse:, the first parameter is the connection which is sending the message. In your case this will be one of the two objects you're creating by calling -getPage:page: twice. So keep track of those objects, and test which one cause the delegate method(s) to be called.

Graham Lee
Added more code above to clarify. I can tell which object I'm getting a response from - but one overwrites the other.
BankStrong
@BankStrong - I don't see anything fishy in the code above. Can you post the NSURLConnection delegate methods, and anywhere that m_Delegate is used?
Dave DeLong
+4  A: 

You said thisPage is a module-level variable. I assume that means that it's not an instance variable. If this is the case, there's only one thisPage variable shared between all instances of CSNet. Naturally, if you have two of them running at once, they'll clobber each other.

If you really want each instance of CSNet to have its own thisPage variable, then make it an instance variable.

BJ Homer
Dead on - thisPage got clobbered (I didn't understand the difference in the possible areas to declare it). Thanks a ton.
BankStrong