使用宏中央调度从文件加载UIImage

时间:2012-05-21 21:27:01

标签: ios grand-central-dispatch

我正在尝试使用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有关,所有这些都在里面。我觉得它应该

时不会被绘制/刷新

3 个答案:

答案 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