CGLayer绘图随着时间的流逝而变慢

sea*_*her 1 core-graphics objective-c quartz-graphics ios

谁能解释为什么重新绘制到屏幕外的CGLayer会导致渲染随时间推移而变慢?让我向您展示我为说明问题而创建的测试。

@implementation DrawView


- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        //setup frame rate monitoring
        fps = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
        fps.textColor = [UIColor whiteColor];
        fps.font = [UIFont boldSystemFontOfSize:15];
        fps.text = @"0 fps";
        [self addSubview:fps];
        frames = 0;
        lastRecord = [NSDate timeIntervalSinceReferenceDate];

        //create a cglayer and draw the background graphic to it
        CGContextRef context = UIGraphicsGetCurrentContext();
        cacheLayer = CGLayerCreateWithContext(context, self.bounds.size, NULL);

        CGImageRef background = [[UIImage imageNamed:@"background.jpg"] CGImage];
        CGContextRef cacheContext = CGLayerGetContext(cacheLayer);
        CGContextDrawImage(cacheContext, CGRectMake(0, 0, 768, 1024), background);

        //initialize cgimage stamp
        stamp = [[UIImage imageNamed:@"stamp.png"] CGImage];
        stampTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:@selector(stamp) userInfo:nil repeats:YES];
    }
    return self;
}

- (void) stamp {
    //calculate fps
    NSTimeInterval interval = [NSDate timeIntervalSinceReferenceDate];
    NSTimeInterval diff = interval-lastRecord;
    if (diff > 1.0) {
        float rate = frames/diff;
        frames = 0;
        lastRecord = [NSDate timeIntervalSinceReferenceDate];
        fps.text = [NSString stringWithFormat:@"%0.1f fps", rate];
    }
    //stamp the offscreen cglayer with the cgimage graphic
    CGRect stampRect = CGRectMake(0, 0, 200, 200);
    CGContextRef cacheContext = CGLayerGetContext(cacheLayer);
    CGContextDrawImage(cacheContext, stampRect, stamp);
    [self setNeedsDisplayInRect:stampRect];
}

- (void)drawRect:(CGRect)dirtyRect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawLayerInRect(context, self.bounds, cacheLayer);
    frames++;
}
Run Code Online (Sandbox Code Playgroud)

当我在ipad模拟器或设备上运行此测试时,它以40 fps的速度开始,并在10秒的过程中以恒定的速率下降,直到以3 fps的速度运行。为什么会这样呢?这不应该以恒定的帧速率运行吗?什么样的解决方案可以让我一遍又一遍地“压印”图像,同时保持恒定的帧速率?

Rob*_*ier 5

您的问题是您使用NULL上下文创建了图层。UIGraphicsGetCurrentContext()仅在绘制循环期间有效。您在draw循环之外调用它,因此它为NULL,因此该图层无法缓存任何内容。这仍然令我感到惊讶,随着时间的流逝,它严重破坏了性能。我怀疑CoreGraphics中可能存在错误;您会认为这只会很慢;而不是“永远放慢脚步”。但是,它并非旨在以这种方式工作。

如果创建位图上下文并将其用于图层,则将获得60fps。您无需在这里放弃CGLayer。

我要恢复到60fps的目的就是替换它:

CGContextRef context = UIGraphicsGetCurrentContext();
Run Code Online (Sandbox Code Playgroud)

有了这个:

CGContextRef context = CreateBitmapContext(self.bounds.size);
Run Code Online (Sandbox Code Playgroud)

哪里CreateBitmapContext()是返回同样的事情,你的功能createBitmapContext设置。