2014-03-04 111 views
2

我正在使用CGlayers用于绘图,正如文档所述,它是在画布上绘制绘图的更高效的方法。CGlayer绘图性能低下

我基本上拉入CGlayers和绘制层成使用CGContextDrawLayerInRect

这里图形上下文是我的drawRect方法

- (void)drawRect:(CGRect)rect 
{  
    switch (m_drawStep) 
    { 
     case DRAW: 
     {    
      CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw) 

      if(self.currentDrawingLayer == nil)//Potential leak of memory- static analyzer 
      { 
       CGFloat scale = self.contentScaleFactor; 
       CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale); 
       CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); 
       CGContextRef layerContext = CGLayerGetContext(layer); 
       CGContextScaleCTM(layerContext, scale, scale); 
       self.currentDrawingLayer = layer; 
      }   

      CGContextRef layerContext = CGLayerGetContext(self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      CGContextBeginPath(layerContext); 
      CGContextAddPath(layerContext, mutablePath); 
      CGContextSetLineWidth(layerContext, self.lineWidth); 
      CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetFillColorWithColor(layerContext, self.lineColor.CGColor); 
      CGContextSetBlendMode(layerContext,kCGBlendModeNormal); 
      CGContextStrokePath(layerContext); 
      CGPathRelease(mutablePath); 

      CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer);//Potential leak of memory- static analyzer 
     } 
      break; 

     case UNDO: 
     {       
      CGContextRef context = UIGraphicsGetCurrentContext();   

      if(self.currentDrawingLayer == nil)//Potential leak of memory- static analyzer 
      { 
       CGFloat scale = self.contentScaleFactor; 
       CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale); 
       CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL); 
       CGContextRef layerContext = CGLayerGetContext(layer); 
       CGContextScaleCTM(layerContext, scale, scale); 
       self.currentDrawingLayer = layer; 
      }         

      CGContextRef layerContext1 = CGLayerGetContext(self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      CGContextClearRect(layerContext1, self.bounds); 

      for(NSArray *undoArray in m_parentUndoArray) 
      { 
       for(int i =0; i<[undoArray count];i++) 
       { 
        DrawingPath *drawPath = [undoArray objectAtIndex:i]; 
        CGPathRef path = drawPath.path.CGPath; 
        mutablePath = CGPathCreateMutableCopy(path); 


        CGContextBeginPath(layerContext1); 
        CGContextAddPath(layerContext1, mutablePath); 
        CGContextSetLineWidth(layerContext1, drawPath.pathWidth.floatValue); 
        CGContextSetStrokeColorWithColor(layerContext1, drawPath.pathColor.CGColor); 

        if([drawPath.pathColor isEqual:[UIColor clearColor]]) 
        { 
         CGContextSetBlendMode(layerContext1,kCGBlendModeClear); 
        } 
        else 
        { 
         CGContextSetBlendMode(layerContext1,kCGBlendModeNormal); 
        } 

         CGContextStrokePath(layerContext1); 
         CGPathRelease(mutablePath); 
        } 
       } 

       CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer);//Potential leak of memory- static analyzer 
      } 
     } 
      break; 



    [super drawRect:rect]; 
} 

以我的触摸已移至函数功能,我创建UIBezeirPath和将其转换为CGPath。

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{   
    self.currentPath = [[DrawingPath alloc] init]; 

    if(m_eraseButtonClicked) 
    { 
     [self.currentPath setPathColor:[UIColor clearColor]];   
    } 
    else 
    { 
     [self.currentPath setPathColor:self.lineColor];    
    } 

    CGPathRef cgPath = self.currentPath.path.CGPath; 
    mutablePath = CGPathCreateMutableCopy(cgPath); 

     [m_undoArray addObject:self.currentPath]; 
     [self setNeedsDisplay]; 

    } 

在触摸结束

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [m_parentUndoArray addObject:[NSArray arrayWithArray:m_undoArray]]; 

} 

其中,我所面临的问题是以下

1)I与时间探查测试,CGContextDrawLayerInRect,需要90%的时间,同时绘制,所以我想知道如何减少这种方法所花费的时间并优化drawRect方法。 2)如果我画几条冗长的线并开始不断地撤消/重做,那么你也可以看到CGContextDrawLayerInRect这需要很多时间。 3)如果我删除了一些画线并重复进行撤消/重做,更糟糕的是,我的应用程序崩溃了内存警告,我不知道擦除出了什么问题,它花费了太多内存。

编辑:代码,更新,以显示在静态分析说,他们是内存问题

+0

Is Instruments是否报告泄漏仪器存在任何内存泄漏?你有僵尸启用(这将导致释放内存永远不会被释放)?您是否在代码中使用Xcode中的静态分析器来查看它是否报告了有关内存管理的任何问题? – Gavin

+0

你好@Gavin,它报告与CoreGraphics功能的内存泄漏,我不知道僵尸,我没有运行任何静态分析器 – Ranjit

+0

我运行静态分析器,其报告的问题在上面的代码行,我已更新。 – Ranjit

回答

0

从我自己的实验,看来iOS的有时会使用GPU,有时CPU进行CGContextDrawLayerInRect,根据大小被复制的图层(以及潜在的其他因素)。当它使用CPU时,速度要慢20倍。

唯一的解决方法是通过使用setNeedsDisplayInRect而不是setNeedsDisplay,并在drawRect代码中添加CGContextClipToRect(context,rect)来减小更新区域的大小。