在背景中绘图

Posted

技术标签:

【中文标题】在背景中绘图【英文标题】:Drawing in the Background 【发布时间】:2014-03-11 23:16:45 【问题描述】:

我有一个 ios 应用程序需要更新视图以响应用户或外部事件。绘制时间可以很短也可以很长(几秒钟),具体取决于视图中的内容。

现在,绘图是在视图的 drawRect 方法中进行的。当绘图很长并且有很多用户交互时,应用程序会变得无响应。

当需要更新时,需要更新整个视图。如果在绘图过程中发生更改,重新启动绘图以将更改考虑在内是有意义的。

我想在后台进行绘图。

我的问题是在 IOS 中执行此操作的最佳机制是什么?

线程,NSOperation?

如何处理绘图?例如,如何在线程中为我正在更新的视图获取图形上下文?

绘图操作应该如何开始?现在我正在做 setNeedsDisplay。我可以改变做其他事情。

有问题的视图在 UIScrollView 中,但没有其他用户交互。

【问题讨论】:

【参考方案1】:

这是一个开始的框架。该代码假定输出视图是 UIImageView。后台任务使用位图内存上下文为输出视图创建新图像。当后台绘制任务完成后,主线程将生成的图像分配给 UIImageView。

sequenceNumber 用于在绘制完成之前丢弃过期的图像。一个可能的问题是事件来得太快以至于每个图像在完成之前就已经过时了。解决这个问题留给读者作为练习。

@interface SomeClass()
@property (weak, nonatomic) IBOutlet UIImageView *someView;
@property (nonatomic) int64_t sequenceNumber;
@end

@implementation SomeClass

- (UIImage *)createImageUsingBitmapMemoryContextOfSize:(CGSize)size

    // create the memory bitmap context
    UIGraphicsBeginImageContext( size );
    CGContextRef context = UIGraphicsGetCurrentContext();

    // draw something
    [[UIColor blueColor] set];
    CGContextFillEllipseInRect( context, CGRectMake(0, 0, size.width, size.height) );

    // create a UIImage 
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // return the image
    return( result );


// Note: the following function should only be called on the main thread
- (void)updateInResponseToSomeEvent

    self.sequenceNumber++;
    int64_t sequenceNumber = self.sequenceNumber;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^
    
        UIImage *image = [self createImageUsingBitmapMemoryContextOfSize:self.someView.bounds.size];
        dispatch_async( dispatch_get_main_queue(), ^
        
            if ( sequenceNumber == self.sequenceNumber )
                self.someView.image = image;
        );
    );

【讨论】:

这正是我所需要的。我的一个问题是,与将图像直接绘制到视图上相比,将图像绘制到图像中会产生高度模糊的图像。有人知道如何纠正吗? 一个可能的解决方案是UIGraphicsBeginImageContextWithOptions( size, YES, 0.0 ); 就是这样。现在我明白了。谢谢。【参考方案2】:

不要在后台绘制视图,因为 UIKit 不是线程安全的!在后台您可以在图像上绘制,绘制完成后,在主线程中更新您的视图。

【讨论】:

以上是关于在背景中绘图的主要内容,如果未能解决你的问题,请参考以下文章

如何在背景图像上绘制(如在 GLPaint 中)并使用临时绘图?

如何在没有背景的情况下保存绘图?

ReadPng,光栅,绘图背景中图片的宽度

将背景图像添加到绘图

c#中使用Graphice类绘图 怎么才能把背景的黑白格去掉或者变透明

菜鸟求助关于Canvas绘图背景问题。