Search code examples
iosselectornsthreadnsoperationqueuesudzc

Wait until multiple NSXMLParser parsing operations are complete


On the login screen of my app, after I get the credentials from the user, I do a series of parsing operations. I'm keeping the data in a Core Data store and I have around 7 entities, meaning I need 7 different parse operations.

I do the parsing with Sudcz;

[WService UserLogin:self withUsername:username andPassword:pwd action:@selector(handleLogin:)];

where handleLogin is the selector doing the parsing. And if the login is successful, I call all the other parse handlers inside this handler.

- (void)handleLogin:(id)value
{
if ([value isKindOfClass:[NSError class]]) {
    NSLog(@"nserror %@", value);
    [managedObjectContext rollback];
    abort();
}
else if ([value isKindOfClass:[SoapFault class]])
{
    NSLog(@"soap fault %@", value);
    abort();
}
else {
    XMLParser *parser = [[XMLParser alloc] init];
    self.user = [[parser parseUserFromXML:value] retain];
    [parser release];

    if(self.user.userID != 0) 
    {
        NSError *error;
        if (![self.managedObjectContext save:&error])
            NSLog(@"Error");
        else
        {
            //calling other handlers for other entities
            SudzcMyWebService *WService = [[SudzcMyWebService alloc] init];
            [WService pharmacyOfUser:self action:@selector(handlePharmacyOfUser:) intUserID:[user.userID intValue]];
            [WService allPharmacyOrder:self byUserID:[user.userID intValue] action:@selector(handlePharmacyOrders:)];
            [WService allPharmacyOrderDetail:self withUserID:[user.userID intValue] action:@selector(handlePharmacyOrderDetails:)];
            [WService allCampaign:self action:@selector(handleCampaigns:)];
            [WService allCampaignDetail:self action:@selector(handleCampaingDetails:)];
            [WService allChannel:self action:@selector(handleChannels:)];
             .....
            //some method finishing the parsing, but not with certainty. this is where i      need help
            [WService release];
        }
    }
    else
    {
        [activityIndicator stopAnimating];
        [self showMessageBox:@"Wrong password or username" title:@"Error"]; 
        [self.managedObjectContext rollback];
    }
}
}

All those handlers work in the same logic. Everything works fine normally. BUT, when something goes wrong like, say, app shuts down in the middle of parsing or one of the parsing has failed, the app tries to open and crashes (NSException) due to missing data.

What I would like to do is tell the app to (kind of) wait until all the parsing is done safely (because the order the selectors (handlers) perform is random, I guess) and all the handlers return some positive result. If not, then reset the persistent store/delete existing incomplete entities and restart.

EDIT: when all the selectors are finished running, i'd like to call a method that will understand if the store is full or not depending on the results coming from those selectors and act accordingly.

How should I go about this? NSOperationQueue or NSThread or something else?

Thanks in advance,

Eren


Solution

  • Use NSUserDefaults to store the programm state / state of the task. If the app crashes it can check the state information and react like it should.

    Here's a simple example how to save the state:

    // load standardUserDefaults
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];  
    // save if operation is finished
    [prefs setBool:YES forKey:@"operationOnefinished"];
    // sync prefs
    [prefs synchronize];
    

    To call [prefs synchronize]; is not needed, because it's invoked automatically at periodic intervals. But since you mentioned, that your app crashes sometimes it's better to call this method to save changes instantly.

    Retrieving states:

    // load standardUserDefaults
    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 
    // Getting state
    BOOL operationOnefinished = [prefs stringForKey:@"operationOnefinished"];