UIImage initWithData:阻止 UI 异步调度线程?
UIImage initWithData: blocking UI thread from async dispatch?
以下代码正在阻止 UI(在图像加载完成之前无法点击另一个选项卡)。
我已经通过注释该行并保持下载(我知道这是异步发生的并在主线程上调用完成处理程序)来验证 UIImage *imageToShow = [[UIImage alloc] initWithData:data];
调用是罪魁祸首。
在只有initWithData:
行被注释的情况下,UI响应是可以的。但是,如果在后台清楚地调度,那条线怎么会是支撑 UI 的线呢?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
...
[objectStore getFileInContainer:@"public_images" filename:filename completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *imageToShow = [[UIImage alloc] initWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
collectionImageView.image = imageToShow;
});
});
}];
...
}
最有可能导致 UI 挂起的部分是图像对图像视图的实际设置,特别是如果图像很大,因为这确实(而且必须)发生在主线程上.
我建议您先在后台线程中操作时调整或缩小图像。然后一旦你调整了图像的大小,跳回到主线程并将它分配给``imageView.image```。
这是调整 UI图像大小的一种方法的简单示例:Resize UIImage by keeping Aspect ratio and width
UIImage
直到第一次实际 used/drawn 才读取和解码图像。要强制此工作在后台线程上进行,您必须在执行主线程 -setImage:
调用之前 use/draw 后台线程上的图像。许多人发现这违反直觉。我在 another answer.
中对此进行了相当详细的解释
以下代码正在阻止 UI(在图像加载完成之前无法点击另一个选项卡)。
我已经通过注释该行并保持下载(我知道这是异步发生的并在主线程上调用完成处理程序)来验证 UIImage *imageToShow = [[UIImage alloc] initWithData:data];
调用是罪魁祸首。
在只有initWithData:
行被注释的情况下,UI响应是可以的。但是,如果在后台清楚地调度,那条线怎么会是支撑 UI 的线呢?
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
...
[objectStore getFileInContainer:@"public_images" filename:filename completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *imageToShow = [[UIImage alloc] initWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
collectionImageView.image = imageToShow;
});
});
}];
...
}
最有可能导致 UI 挂起的部分是图像对图像视图的实际设置,特别是如果图像很大,因为这确实(而且必须)发生在主线程上.
我建议您先在后台线程中操作时调整或缩小图像。然后一旦你调整了图像的大小,跳回到主线程并将它分配给``imageView.image```。
这是调整 UI图像大小的一种方法的简单示例:Resize UIImage by keeping Aspect ratio and width
UIImage
直到第一次实际 used/drawn 才读取和解码图像。要强制此工作在后台线程上进行,您必须在执行主线程 -setImage:
调用之前 use/draw 后台线程上的图像。许多人发现这违反直觉。我在 another answer.