【发布时间】:2013-10-11 07:57:31
【问题描述】:
我有一个带有 UIImageView 子视图的 UIView。我需要在不阻塞 UI 的情况下在 UIImageView 中加载图像。阻塞调用似乎是:UIImage imageNamed:。这是我认为解决此问题的方法:
-(void)updateImageViewContent {
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
UIImage * img = [UIImage imageNamed:@"background.jpg"];
dispatch_sync(dispatch_get_main_queue(), ^{
[[self imageView] setImage:img];
});
});
}
图片很小 (150x100)。
但是,加载图像时 UI 仍然被阻止。我错过了什么?
这是一个展示这种行为的小代码示例:
基于 UIImageView 创建一个新类,将其用户交互设置为 YES,在一个 UIView 中添加两个实例,并实现其 touchesBegan 方法,如下所示:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
if (self.tag == 1) {
self.backgroundColor= [UIColor redColor];
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self setImage:[UIImage imageNamed:@"woodenTile.jpg"]];
});
[UIView animateWithDuration:0.25 animations:
^(){[self setFrame:CGRectInset(self.frame, 50, 50)];}];
}
}
将标签 1 分配给这些 imageView 之一。
当您几乎同时点击两个视图(从加载图像的视图开始)时,究竟会发生什么? UI 是否因为等待[self setImage:[UIImage imageNamed:@"woodenTile.jpg"]]; 返回而被阻止?如果是这样,我该如何异步执行此操作?
这是一个project on github,带有ipmcc 代码
使用长按然后拖动以在黑色方块周围绘制一个矩形。据我了解他的回答,理论上白色选择矩形不应该在第一次加载图像时被阻止,但实际上是。
项目中包含两张图片(一张小的:woodenTile.jpg 和一张大的:bois.jpg)。结果是一样的。
图片格式
我不太明白这与第一次加载图像时 UI 被阻塞的问题有什么关系,但是 PNG 图像在不阻塞 UI 的情况下解码,而 JPG 图像确实阻塞了 UI .
大事记
UI 的阻塞从这里开始..
.. 到此结束。
AFNetworking 解决方案
NSURL * url = [ [NSBundle mainBundle]URLForResource:@"bois" withExtension:@"jpg"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[self.imageView setImageWithURLRequest:request
placeholderImage:[UIImage imageNamed:@"placeholder.png"]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
NSLog(@"success: %@", NSStringFromCGSize([image size]));
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(@"failure: %@", response);
}];
// this code works. Used to test that url is valid. But it's blocking the UI as expected.
if (false)
if (url) {
[self.imageView setImage: [UIImage imageWithData:[NSData dataWithContentsOfURL:url]]]; }
大多数时候,它会记录:success: {512, 512}
它偶尔也会记录:success: {0, 0}
有时:failure: <NSURLResponse: 0x146c0000> { URL: file:///var/mobile/Appl...
但图像永远不会改变。
【问题讨论】:
-
你什么都没有。 UI 更改始终必须是同步的。这是你能做的最好的。
-
图片有多大?您可能会发现阻塞调用不是加载图像,而是在图像视图显示在屏幕上时渲染图像的内容。您是否尝试过分析应用程序以查看瓶颈在哪里,您是否只是盲目地假设图像加载是问题?
-
我最初是在类方法中加载图像,对于类的所有实例只加载一次。阻塞只是第一次发生,这让我认为它是由 UIImage imageNamed 引起的。
-
使用仪器找到瓶颈。
-
看我的问答here。
标签: ios objective-c uiimageview grand-central-dispatch