在 for 循环中处理 UI 更新 - iOS
Handling UI update in a for loop - iOS
我正在使用 NSNotificationcentre 从 for 循环更新 UI。 UI 在执行退出循环之前不会更新。有办法处理这种情况吗? 下面是我的代码:
- (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];
}
在我的 viewcontroller.m 文件中,我在 viewdidLoad()
下声明了观察者[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updatePreviewView:) name:kUpdatePreviewImageView object:nil];
更新预览:class定义如下:
-(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];
}
由于 for 循环是 运行主线程,该线程会被阻塞,直到 for 查找完成。由于主要威胁也是 UI 线程,您的 UI 更新在循环完成之前不会完成。
您应该 运行 后台线程上的循环和 UI 更改应该是 运行 主线程上的异步。
并在您的 updatePreviewView:
中确保代码 运行 在主线程上。
这样做:
-(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];
});
}
你应该把它放在主线程中。但是 NSOperationQueue 可能不会在 for 循环中发送所有内容。您可以在异步队列中进行操作并在没有 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];
});