2015-12-01 1 views
2

В настоящее время я изучаю чертеж с UIView и CALayer. Я быстро сделал приложение для рисования, чтобы поэкспериментировать с двумя классами. Я заметил, что CALayer хуже, чем UIView. Вот код:iOS: почему UIView's drawRect имеет лучшую производительность, чем DrawIcontext CALayer

myView.m

@interface myView() 

@property (nonatomic, strong) UIImageView *background; 

#ifdef USE_LAYER 
@property (nonatomic, strong) drawingLayer *drawCanvas; 
#else 
@property (nonatomic, strong) drawingView *drawCanvas; 
#endif 
@end 

@implementation myView 

- (instancetype)initWithFrame:(CGRect)frame 
{ 
    if (self = [super initWithFrame:frame]) 
    { 
     self.background = [[UIImageView alloc] initWithFrame:frame]; 
     [self addSubview:self.background]; 
#ifdef USE_LAYER 
     self.drawCanvas = [[drawingLayer alloc] init]; 
     self.drawCanvas.frame = frame; 
     [self.layer addSublayer:self.drawCanvas]; 
#else 
     self.drawCanvas = [[drawingView alloc] initWithFrame:frame]; 
     self.drawCanvas.backgroundColor = [UIColor clearColor]; 
     [self addSubview:self.drawCanvas]; 
#endif 
    } 
    return self; 
} 

- (CGPoint)getPoint:(NSSet<UITouch *> *)touches 
{ 
    NSArray *touchesArray = [touches allObjects]; 
    UITouch *touch = (UITouch *)[touchesArray objectAtIndex:0]; 
    return [touch locationInView:self]; 
} 

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint point = [self getPoint:touches]; 
    self.drawCanvas.points = [[NSMutableArray alloc] init]; 
    self.drawCanvas.startPoint = point; 
} 

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint point = [self getPoint:touches]; 
    [self.drawCanvas.points addObject:[NSValue valueWithCGPoint:point]]; 
    self.background.image = [self imageFromLayer:self.layer]; 
    self.drawCanvas.points = nil; 
    [self.drawCanvas setNeedsDisplay]; 
} 

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 
{ 
    CGPoint point = [self getPoint:touches]; 
    [self.drawCanvas.points addObject:[NSValue valueWithCGPoint:point]]; 
    [self.drawCanvas setNeedsDisplay]; 
} 

- (UIImage *)imageFromLayer:(CALayer *)layer 
{ 
    UIGraphicsBeginImageContext([layer frame].size); 
    [layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return outputImage; 
} 

@end 

drawingView.h

@interface drawingView : UIView 

@property (nonatomic, assign) CGPoint startPoint; 
@property (nonatomic, strong) NSMutableArray *points; 

@end 

drawingView.m

@implementation drawingView 

- (void)drawRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); 

    CGContextSetLineWidth(context, 2.0f); 
    CGContextMoveToPoint(context, self.startPoint.x, self.startPoint.y); 

    for (NSValue *point in self.points) 
    { 
     CGPoint location = [point CGPointValue]; 
     CGContextAddLineToPoint(context, location.x, location.y); 
    } 
    CGContextStrokePath(context); 
} 

@end 

У меня также есть "drawingLayer", который, по существу, то же самое как «drawingView», за исключением подкласса CALayer и делает тот же рисунок в «drawInContext».

То, что я нашел, было то, что drawRect имеет намного лучшую производительность, рисунок почти синхронно с положением касания, с очень небольшим отставанием. Почему это так? Я ожидал, что рисунок CALayer будет по крайней мере одинаковым, если не лучше. Фактически, кто-то сказал мне сегодня, что рисование в CALayer аппаратно ускорено, что является предпочтительным способом, если производительность является проблемой. Конечно, это не так в моем маленьком эксперименте. Зачем?

+0

CALayer анимации может сделать вид, медленнее в движении. Возможно, это то, что вы наблюдаете. –

+0

Чувствуете ли вы, что это медленнее, или это действительно так? Вы использовали Инструменты для проверки этого? Кроме того, вы попробовали обновить cgPath CAShapeLayer? Это может повысить производительность. – Lepidopteron

ответ

0

Это может быть вызвано анимацией по умолчанию CALayer.

Попробуйте переопределить action(forKey event: String) -> CAAction? и всегда возвращают nil в то время как подклассы CALayer класса