相关疑难解决方法(0)

如何在UIImageView中异步加载图像?

我有一个带有UIImageView子视图的UIView.我需要在UIImageView中加载图像而不阻止UI.阻塞呼叫似乎是: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];
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

图像很小(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)];}];
    }
}
Run Code Online (Sandbox Code Playgroud)

将标记1分配给其中一个imageView.

从加载图像的视图开始几乎同时点击两个视图时会发生什么?UI是否因为等待[self setImage:[UIImage imageNamed:@"woodenTile.jpg"]];返回而被阻止?如果是这样,我该如何异步执行此操作?

这是一个 带有ipmcc代码的github项目

使用长按然后拖动在黑色方块周围绘制一个矩形.据我理解他的答案,理论上白色选择矩形不应该在第一次加载图像时被阻挡,但实际上是.

项目中包含两个图像(一个小图片:woodenTile.jpg和一个较大图片:bois.jpg).结果与两者相同.

图片格式

我真的不明白这与第一次加载图像时UI被阻止的问题有什么关系,但是PNG图像在不阻挡UI的情况下进行解码,而JPG图像会阻止UI.

事件的年表

第0步 步骤1

UI的阻止从这里开始..

第2步

..并在此结束.

第3步

AFNetworking解决方案

    NSURL * url = …
Run Code Online (Sandbox Code Playgroud)

objective-c uiimageview grand-central-dispatch ios

25
推荐指数
3
解决办法
3万
查看次数

在UI线程上懒洋洋地加载CGImage/UIImage会导致口吃

我的程序显示一个水平滚动表面,从左到右平铺UIImageViews.代码在UI线程上运行,以确保新显示的UIImageViews分配了一个新加载的UIImage.加载发生在后台线程上.

一切都很好,除了每个图像变得可见时都有口吃.起初我以为我的后台工作者在UI线程中锁定了一些内容.我花了很多时间查看它,并最终意识到UIImage在UI线程第一次变得可见时正在做一些额外的延迟处理.这让我很困惑,因为我的工作线程有明确的解压缩JPEG数据的代码.

无论如何,在预感上,我写了一些代码,以渲染到后台线程上的临时图形上下文中 - 当然,口吃也消失了.UIImage现在正在我的工作线程上预先加载.到现在为止还挺好.

问题是我的新"强力懒惰的图像"方法是不可靠的.它会导致间歇性的EXC_BAD_ACCESS.我不知道UIImage在幕后实际上在做什么.也许它正在解压缩JPEG数据.无论如何,方法是:

+ (void)forceLazyLoadOfImage: (UIImage*)image
{
 CGImageRef imgRef = image.CGImage;

 CGFloat currentWidth = CGImageGetWidth(imgRef);
 CGFloat currentHeight = CGImageGetHeight(imgRef);

    CGRect bounds = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);

 CGAffineTransform transform = CGAffineTransformIdentity;
 CGFloat scaleRatioX = bounds.size.width / currentWidth;
 CGFloat scaleRatioY = bounds.size.height / currentHeight;

 UIGraphicsBeginImageContext(bounds.size);

 CGContextRef context = UIGraphicsGetCurrentContext();
 CGContextScaleCTM(context, scaleRatioX, -scaleRatioY);
 CGContextTranslateCTM(context, 0, -currentHeight);
 CGContextConcatCTM(context, transform);
 CGContextDrawImage(context, CGRectMake(0, 0, currentWidth, currentHeight), imgRef);

 UIGraphicsEndImageContext();
}
Run Code Online (Sandbox Code Playgroud)

并且EXC_BAD_ACCESS发生在CGContextDrawImage行上.问题1:我是否允许在UI线程以外的线程上执行此操作?问题2:什么是UIImage实际上"预加载"?问题3:解决这个问题的官方方法是什么?

感谢阅读所有这些,任何建议将不胜感激!

iphone lazy-loading exc-bad-access uiimage cgimage

12
推荐指数
3
解决办法
1万
查看次数

UITableView平滑滚动

我在每个单元格中都有UITableView图像,我希望滚动顺畅.所以我在stackerflow上阅读了一些帖子,现在我在后台线程中加载我的图片:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell: BuildingStatusCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! BuildingStatusCell
    cell.selectionStyle = UITableViewCellSelectionStyle.None
    var node = nodesArray[indexPath.row] as! NSMutableDictionary
    if !checkIfImagesLoaded(node[Api.pictures] as! NSMutableArray) {
        cell.id = node[Api.buildingStatusId] as! Int
        cell.date.text =  node[Api.date] as? String
        cell.count.text = String((node[Api.pictures] as! NSMutableArray).count)
        cell.indicator.hidesWhenStopped = true
        cell.indicator.startAnimating()
        dbHelper.getBuildingStatusNode(node, callback: self)
    } else {
        cell.id = node[Api.buildingStatusId] as! Int
        cell.date.text =  node[Api.date] as? String
        cell.count.text = String((node[Api.pictures] as! NSMutableArray).count)
        dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
            var image = …
Run Code Online (Sandbox Code Playgroud)

uitableview ios swift

1
推荐指数
1
解决办法
4763
查看次数