我正在尝试使用gcd在后台加载图片。我的第一次尝试不起作用:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
// create UI Image, add to subview
});
});
注释掉后台队列代码并且只留下主队列调度块不起作用:
dispatch_async(dispatch_get_main_queue(), ^{
// create UI Image, add to subview
});
在gcd块中做ui的东西有什么技巧吗?
在回应mattjgalloway的评论时,我只是想在后台线程中加载一个大图像。这是我最初尝试的完整代码:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.frame;
imageView.frame = photoFrame;
[self addSubview:imageView];
});
});
我简化了它,以便我在主队列中运行所有内容,但即使这样它也无法正常工作。我想如果我不能让整个事情在主队列中工作,那么后台队列的东西就不会起作用。
================更新==============
我在一个全新的项目中尝试了上述技术(gcd和all),它确实按预期工作。只是不在我目前的项目中。因此,我将不得不做一些缓慢而痛苦的淘汰工作来弄清楚出了什么问题。我正在使用此背景加载来在uiscrollview中显示图像。结果显示有时会出现的图像比特,但并非总是如此。我会深究这个......
================更新==============
看起来这个问题与UIScrollView有关,所有这些都在里面。我觉得它应该
时不会被绘制/刷新答案 0 :(得分:1)
我运行了你的代码。它有一个例外。你的意思是自我观而不是自我吗?
案例1:
路径在属性中声明 imageView在ivar中声明
- (IBAction)buttonImagePressed:(id)sender
{
self.path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"picture1.jpg"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: self.path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.view.frame;
imageView.frame = photoFrame;
[self.view addSubview:imageView];
});
});
}
案例2:
path和imageView都是ivars。 - 没有使用任何财产。
- (IBAction)buttonImagePressed:(id)sender
{
// will crash if path is defined here
// path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"picture1.jpg"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
//if path is defined here then it will work
path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"picture1.jpg"];
UIImage* img = [[UIImage alloc] initWithContentsOfFile:path];
dispatch_async(dispatch_get_main_queue(), ^{
imageView = [[[UIImageView alloc] initWithImage: img] autorelease];
imageView.contentMode = UIViewContentModeScaleAspectFill;
CGRect photoFrame = self.view.frame;
imageView.frame = photoFrame;
[self.view addSubview:imageView];
});
});
}
在案例2中,崩溃的地方,控制台中的消息说在apple.com上提交了一个错误...
答案 1 :(得分:1)
尝试在setNeedDisplay
之后立即调用[self addSubview:imageView]
,顺便说一下大多数UIKit都不是线程安全的,我不知道具体的UIImage方法(在iOS4及更高版本上可能没问题),但我不会这样做。如果要从背景加载图像,请更好地使用线程安全的ImageIO或Core Graphics功能
另一种方法是在后台线程上加载带有图像数据的NSData对象,然后在主线程上调用[UIImage alloc]inithWithData: data]
。
答案 2 :(得分:0)
将我的图像显示为背景图像,而不是作为子视图添加的UIImageView。不知道为什么
@interface PhotoView(){
UIImageView* imageView;
}
@end
@implementation PhotoView
-(id)initWithFrame:(CGRect)frame andPathToPhoto:(NSString*)path andSequenceView:(SequencerView*) sequencerView{
if(self = [super initWithFrame:frame]){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0), ^{
UIImage* img = [[UIImage alloc] initWithContentsOfFile: path];
dispatch_async(dispatch_get_main_queue(), ^{
self.backgroundColor = [UIColor colorWithPatternImage:img];
});
[img release];
});
}
return self;
}
@end