Reputation: 1175
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
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
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
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