DesperateLearner
DesperateLearner

Reputation: 1175

Handling UI update in a for loop - iOS

I'm using NSNotificationcentre to update the UI from a for loop. The UI isn't updated until the execution is out of the loop. Is there way to handle this case? Here is my code below:

- (void)uploadContent{
    NSURLResponse *res = nil;
    NSError *err = nil;



    for (int i = 0; i < self.requestArray.count; i++) {

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [[NSNotificationCenter defaultCenter] postNotificationName:kUpdatePreviewImageView object:nil userInfo:@{@"image":     [self.imageArray objectAtIndex:i],@"count":[NSNumber numberWithInt:i],@"progress":[NSNumber numberWithFloat:0.5f]}];
        }];
        ImageUploadRequest *request = [self.requestArray objectAtIndex:i];


        NSData *data = [NSURLConnection sendSynchronousRequest:request.urlRequest returningResponse:&res error:&err];
        if (err) {

            NSLog(@"error:%@", err.localizedDescription);
        }
        NSError *jsonError;
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&jsonError];

        NSLog(@"current thread %@",[NSThread currentThread]);

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [[NSNotificationCenter defaultCenter] postNotificationName:kUpdatePreviewImageView object:nil userInfo:@{@"image":[self.imageArray objectAtIndex:i],@"count":[NSNumber numberWithInt:i],@"progress":[NSNumber numberWithFloat:1.0f]}];
        }];
    }


    [[NSNotificationCenter defaultCenter] postNotificationName:kImageUploaded object:nil];


}

In my viewcontroller.m file I have the observer declared under viewdidLoad()

[[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(updatePreviewView:) name:kUpdatePreviewImageView object:nil];

The updatepreview: class is defined below:

-(void)updatePreviewView:(NSNotification *)notify{


    NSDictionary *previewImageDetails = [notify userInfo];

    self.previewImageView.image = previewImageDetails[@"image"];



    hud.labelText = [NSString stringWithFormat:@"Uploading media %@ of %lu",previewImageDetails[@"count"],(long unsigned)self.mediaDetail.count];


    hud.progress = [previewImageDetails[@"progress"] floatValue];

}

Upvotes: 0

Views: 555

Answers (3)

kocakmstf
kocakmstf

Reputation: 135

You should take it in the main thread. But NSOperationQueue could be not sending all in for loop. You can take operation in async queue and send it without NSOperationQueue

      dispatch_async(dispatch_get_main_queue(), ^{
  NSDictionary *previewImageDetails = [notify userInfo];
    self.previewImageView.image = previewImageDetails[@"image"];
    hud.labelText = [NSString stringWithFormat:@"Uploading media %@ of %lu",previewImageDetails[@"count"],(long unsigned)self.mediaDetail.count];

    hud.progress = [previewImageDetails[@"progress"] floatValue];
});

Upvotes: 1

cohen72
cohen72

Reputation: 2988

Do this:

-(void)updatePreviewView:(NSNotification *)notify{

    dispatch_async(dispatch_get_main_queue(), ^{
        NSDictionary *previewImageDetails = [notify userInfo];
        self.previewImageView.image = previewImageDetails[@"image"];
        hud.labelText = [NSString stringWithFormat:@"Uploading media %@ of %lu",previewImageDetails[@"count"],(long unsigned)self.mediaDetail.count];
        hud.progress = [previewImageDetails[@"progress"] floatValue];
    });
}

Upvotes: 1

rckoenes
rckoenes

Reputation: 69469

Since the for loop is running the main thread this thread gets blocked until the for look is completed. Since the main threat is also the UI thread your UI updated aren't done until the loop is finished.

You should run the loop on a background thread an the UI changes should them be run asynchronies on the main thread.

And in your updatePreviewView: make sure the code will run on the main thread.

Upvotes: 2

Related Questions