views:

23

answers:

2

Hello all,

This is a follow-up to a previous post regarding the CHCSVParser from Dave DeLong. In short, I am using the CHCSVParser to work with an extremely large CSV file and parse the lines into Core Data entities (on an iPhone). I've got the parser hooked up and working, and am now trying to display a progress indicator to the user.

I ask the app's user to provide a name for the list to be imported with a modal view controller, but the problem I am running into is that the screen looks "stuck" while the parser is running and the modal VC appears frozen (looks like it's not dismissed). No matter how I arrange the code, it seems that the parser is locking everything up while it runs, so the modal VC doesn't get animated out and the progress indicator (a simple UIView and UILabel) is hidden.

I've never programmed with threads before, but this sounds kinda thready to me. How can I address this?

Thanks!

the code:

==== CALLBACK METHOD FROM THE MODAL VC ====

//
// Dismiss the modal VC
//
[self dismissModalViewControllerAnimated:NO];

//
// Set up the progress indicator view
//
progressView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320,480)];
progressView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:.9];

UILabel *progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 150, 300, 60)];
progressLabel.backgroundColor = [UIColor clearColor];
progressLabel.textAlignment = UITextAlignmentCenter;
progressLabel.tag = 12345;
progressLabel.text = NSLocalizedString(@"Beginning import...",@"");
progressLabel.textColor = [UIColor whiteColor];
[progressView addSubview:progressLabel];

[self.view addSubview:progressView];

//
// If a name was provided, then create a List with the given name then parse the
// selected CSV file into it
//
if (listName != nil) {
    // Create the new List object and set the currentList to point to it.
    NSError *error = nil;
    NSEntityDescription *ed = [NSEntityDescription entityForName:@"FOList" inManagedObjectContext:managedObjectContext];
    FOList *theList = [NSEntityDescription insertNewObjectForEntityForName:[ed name] inManagedObjectContext:managedObjectContext];
    theList.name = listName;
    if (![managedObjectContext save:&error]) {
        NSLog(@"Error saving the new list! %@ %@", [error localizedDescription], [error userInfo]);
    }
    currentList = theList;

    //
    // Grab the appropriate file
    //
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSURL *inputFileURL = [NSURL fileURLWithPath: [documentsDirectory stringByAppendingPathComponent:selectedFileName]];

    //
    // Start the parsing
    //
    NSStringEncoding encoding = 0;
    CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVFile:[inputFileURL path] usedEncoding:&encoding error:nil];
    [p setParserDelegate:self];
    numRowsParsed = [NSNumber numberWithInt:0];
    [p parse];
    [p release];
A: 

Perfect job for NSOperation or NSInvocationOperation.

Joshua Nozzi
+1  A: 

Answered my own question here. After a bit of digging I found a good article here. NSOperationQueues were a bit overkill here, and all I needed were the methods – performSelectorInBackground:withObject: and – performSelectorOnMainThread:withObject:waitUntilDone:. These methods will handle the background and main threads for you and make it easy as pie!

Neal L
+1 this is probably the easiest way to do it (since `CHCSVParser` is synchronous), but I'm not sure what progress you'll display, since there's no way to know beforehand how many csv lines are in the file (unless you figure it out some other way). If all you're doing is incrementing a counter, then this is just fine.
Dave DeLong
All I'm doing is overlaying a Black translucent UIView with a white-text UILabel that displays the count of records processed every 100 records or so. The data files take about 5 minutes to process on the phone so I just want to let the user know the app hasn't locked up. Thanks again!
Neal L