Search code examples
iosuialertviewuiprogressview

UiAlertView with UIProgressView for copying files locally


I've been trying to get this working for a day now and I'm still failing. I want to copy a number of files into the Documents folder of my app from the bundle when the app is installed, but this makes the user wait for a long time with the app showing the splash screen.

So I thought I'd make an initial UIAlertView with a UIProgressView as a subview that gets updated every time a file is copied into the documents folder. However the alert shows and the progress bar never gets updated. My logic was:

  • Set up the UIProgressView and UIAlertView as instance variables of my ViewController.
  • In ViewDidLoad, present the alert and set the delegate
  • In - (void)didPresentAlertView:(UIAlertView *)alertView perform a for loop that copies the files and updates the UI. the code was :

    - (void)didPresentAlertView:(UIAlertView *)alertView{
        NSString *src, *path;
        src = // path to the Bundle folder where the docs are stored //
        NSArray *docs = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:src error:nil];
    
        float total = (float)[docs count];
        float index = 1;
    
        for (NSString *filename in docs){
            path = [src stringByAppendingPathComponent:filename];
            if ([[NSFileManager defaultManager]fileExistsAtPath:path]) {
                ... // Copy files into documents folder
                [self performSelectorOnMainThread:@selector(changeUI:) withObject:[NSNumber numberWithFloat:index/total] waitUntilDone:YES];                
                index++;
            }
        }
    [alertView dismissWithClickedButtonIndex:-1 animated:YES];
    }
    

And the code for ChangeUI is

- (void) changeUI: (NSNumber*)value{
    NSLog(@"change ui %f", value.floatValue);
    [progressBar setProgress:value.floatValue];
}

However this just updates the UI from 0 to 1, although the NSLog prints all the intermediate values. Does anyone here know what I'm doing wrong?

Thanks in advance.


Solution

  • The problem is that your loop is on the main thread, and thus the UI has no chance to update until the very end. Try doing the work on a background thread using GCD:

    dispatch_async(DISPATCH_QUEUE_PRIORITY_DEFAULT, ^
        {
            NSString *src, *path;
            src = // path to the Bundle folder where the docs are stored //
            NSArray *docs = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:src error:nil];
    
            float total = (float)[docs count];
            float index = 1;
    
            for (NSString *filename in docs){
                path = [src stringByAppendingPathComponent:filename];
                if ([[NSFileManager defaultManager]fileExistsAtPath:path]) {
                    ... // Copy files into documents folder
                    dispatch_async(dispatch_get_main_queue(), ^{ [self changeUI:[NSNumber numberWithFloat:index/total]]; } );
    
                    index++;
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{ [alertView dismissWithClickedButtonIndex:-1 animated:YES]; } );
        } );