在drawRect方法中繪制大量的線條數(shù)據(jù)時藏畅,會出現(xiàn)卡頓xianxiang寸五。無論是通過異步去移動UIBezerPath還是適當(dāng)?shù)膬?yōu)化數(shù)據(jù)量都無法解決[path stroke]花費(fèi)的時間站楚。
經(jīng)過測試通過layer的異步繪制可以方便的實(shí)現(xiàn)功能苹享。
注意:
_layer.drawsAsynchronously = YES;實(shí)現(xiàn)異步繪制
_layer.contentsScale = [UIScreen mainScreen].scale;防止模糊
_layer的代理不能是UIView逢并,如果在view中添加的layer設(shè)置代理东囚,可以定義一個中間對象作為代理
在代理方法
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
中用UIGraphicPush(),和UIGraphicPop可以將CGContextRef上下文引用壓入當(dāng)前方法中跺嗽,這樣就可以像drawRect方法一樣直接進(jìn)行繪制工作了。
@interface ViewController ()<CALayerDelegate>
@property (nonatomic, strong) UIBezierPath *path;
@property (nonatomic, strong) CALayer *layer;
@property (nonatomic, strong) NSArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_layer = [CALayer layer];
_layer.delegate = self;
_layer.drawsAsynchronously = YES;
_layer.frame = self.view.bounds;
_layer.contentsScale = [UIScreen mainScreen].scale;
[self.view.layer addSublayer:_layer];
[NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
[self setModels:self.array];
}];
}
- (NSArray *)array {
if (!_array) {
NSInteger count = 20000;
NSMutableArray *arr = [NSMutableArray arrayWithCapacity:count];
for (NSInteger i = 0; i < count; i++) {
Model *model = [[Model alloc] init];
model.x = [UIScreen mainScreen].bounds.size.width / count * i;
model.y = arc4random() % 400 + 50;
[arr addObject:model];
};
_array = [arr copy];
}
return _array;
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
if (_path && !_path.isEmpty) {
NSLog(@"開始繪制==");
CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextSetLineWidth(ctx, 1);
CGContextAddPath(ctx, _path.CGPath);
CGContextStrokePath(ctx);
NSLog(@"結(jié)束繪制");
}
}
- (void)setModels:(NSArray *)models {
NSLog(@"設(shè)置了model");
_path = [UIBezierPath bezierPath];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (NSInteger i = 0; i < models.count; i++) {
Model *mod = [models objectAtIndex:i];
if (i == 0) {
[self.path moveToPoint:CGPointMake(mod.x, mod.y)];
}
else {
[self.path addLineToPoint:CGPointMake(mod.x, mod.y)];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.layer setNeedsDisplay];
});
});
}
- (void)dealloc {
self.layer.delegate = nil;
}