Objective-C执行-(void)drawOtherImage耗时约0.03s,
Swift执行drawOtherImage()耗时约0.006s。
1. 画板使用Objective-C语言
@interface DrawBoard : UIImageView
@end
#import "DrawBoard.h"
@protocol PaintBrush
- (void)drawInContent:(CGContextRef)content;
@end
@interface BaseBrush : NSObject
@property (nonatomic, assign) CGPoint startPoint;
@property (nonatomic, assign) CGPoint endPoint;
@property (nonatomic, assign) CGPoint lastPoint;
@property (nonatomic, assign) CGFloat strokeWidth;
- (void)drawInContent:(CGContextRef)content;
@end
@implementation BaseBrush
- (void)drawInContent:(CGContextRef)content{
NSAssert(NO, @"need to implement the method in subclass");
}
@end
@interface Pencil : BaseBrush
@end
@implementation Pencil
- (void)drawInContent:(CGContextRef)content{
if(self.lastPoint.x && self.lastPoint.y){
CGContextMoveToPoint(content, self.lastPoint.x, self.lastPoint.y);
CGContextAddLineToPoint(content, self.endPoint.x, self.endPoint.y);
}else{
CGContextMoveToPoint(content, self.startPoint.x, self.startPoint.y);
CGContextAddLineToPoint(content, self.endPoint.x, self.endPoint.y);
}
}
@end
typedef NS_ENUM(NSInteger, DrawStatus) {
DrawStatusNone,
DrawStatusBegan,
DrawStatusMoved,
DrawStatusEnded
};
@interface DrawBoard()
@property (nonatomic, assign) DrawStatus drawStatus;
@property (nonatomic, strong) BaseBrush *brush;
@property (nonatomic, strong) UIColor *strokeColor;
@property (nonatomic, assign) CGFloat strokeWidth;
@property (nonatomic, strong) NSMutableArray *sendPoints;
@property (nonatomic, strong) UIImage *realImage;
@end
@implementation DrawBoard
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.drawStatus = DrawStatusNone;
self.strokeWidth = 2;
self.strokeColor = [UIColor blackColor];
self.brush = [[Pencil alloc] init];
self.sendPoints = [NSMutableArray array];
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if(self.brush){
self.drawStatus = DrawStatusBegan;
self.brush.lastPoint = CGPointZero;
self.brush.startPoint = [touches.anyObject locationInView:self];
self.brush.endPoint = [touches.anyObject locationInView:self];
[self.sendPoints addObject:[NSValue valueWithCGPoint:self.brush.startPoint]];
// [self drawImage];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if(self.brush){
self.drawStatus = DrawStatusMoved;
self.brush.endPoint = [touches.anyObject locationInView:self];
[self.sendPoints addObject:[NSValue valueWithCGPoint:self.brush.endPoint]];
// [self drawImage];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if(self.brush){
self.drawStatus = DrawStatusEnded;
self.brush.endPoint = [touches.anyObject locationInView:self];
[self.sendPoints addObject:[NSValue valueWithCGPoint:self.brush.endPoint]];
// [self drawImage];
// 发送消息
[self drawOtherImage];
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
if(self.brush){
self.drawStatus = DrawStatusNone;
self.brush.endPoint = CGPointZero;
// 发送消息
[self drawOtherImage];
}
}
// 画自己的线
- (void)drawImage{
/*
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
CGContextRef content = UIGraphicsGetCurrentContext();
[[UIColor clearColor] setFill];
CGContextFillRect(content, self.bounds);
CGContextSetStrokeColorWithColor(content, _strokeColor.CGColor);
CGContextSetLineCap(content, kCGLineCapRound);
CGContextSetLineWidth(content, _strokeWidth);
if(_realImage){
[_realImage drawInRect:self.bounds];
}
self.brush.strokeWidth = self.strokeWidth;
[self.brush drawInContent:content];
CGContextStrokePath(content);
UIImage *preImage = UIGraphicsGetImageFromCurrentImageContext();
self.realImage = preImage;
UIGraphicsEndImageContext();
self.image = preImage;
self.brush.lastPoint = self.brush.endPoint;
*/
}
// 画发过来的线
- (void)drawOtherImage{
NSLog(@"start: %f",[[NSDate date] timeIntervalSince1970]);
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
CGContextRef content = UIGraphicsGetCurrentContext();
[[UIColor clearColor] setFill];
CGContextFillRect(content, self.bounds);
CGContextSetStrokeColorWithColor(content, _strokeColor.CGColor);
CGContextSetLineCap(content, kCGLineCapRound);
CGContextSetLineWidth(content, _strokeWidth);
if(self.realImage){
[self.realImage drawInRect:self.bounds];
}
[_sendPoints enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CGPoint point = [(NSValue *)obj CGPointValue];
if(idx == 0){
CGContextMoveToPoint(content, point.x, point.y);
}else{
CGContextAddLineToPoint(content, point.x, point.y);
}
}];
CGContextStrokePath(content);
UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
self.realImage = resImage;
UIGraphicsEndImageContext();
self.image = resImage;
self.sendPoints = [NSMutableArray array];
NSLog(@"end: %f",[[NSDate date] timeIntervalSince1970]);
}
@end
2. 画板使用Swift语言
import UIKit
import CoreGraphics
protocol PaintBrush {
func drawInContext(_ context: CGContext)
}
class BaseBrush: NSObject, PaintBrush {
var startPoint: CGPoint!
var endPoint: CGPoint!
var lastPoint: CGPoint?
var strokeWidth: CGFloat!
func drawInContext(_ content: CGContext) {
assert(false,"need to implement the method in subclass")
}
}
class PencilBrush: BaseBrush {
override func drawInContext(_ context: CGContext) {
if let lastPoint = self.lastPoint{
context.move(to: lastPoint)
context.addLine(to: endPoint);
}else{
context.move(to: startPoint);
context.addLine(to: endPoint);
}
}
}
class EraserBrush: PencilBrush{
override func drawInContext(_ context: CGContext) {
context.setBlendMode(.clear)
super.drawInContext(context)
}
}
enum DrawingState {
case no, began, moved, ended
}
class Board: UIImageView {
private var drawState: DrawingState!
private var realImage: UIImage?
var brush: BaseBrush?
var strokeWidth: CGFloat
var strokeColor: UIColor
var sendPoints: [CGPoint] = []
override init(frame: CGRect) {
self.drawState = .no
self.strokeWidth = 1
self.strokeColor = UIColor.white
super.init(frame: frame)
}
required init(coder aDecoder: NSCoder) {
self.drawState = .no
self.strokeWidth = 1
self.strokeColor = UIColor.white
super.init(coder: aDecoder)!
}
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
if self.brush != nil{
self.brush?.lastPoint = nil
self.brush?.startPoint = touches.first?.location(in: self)
self.brush?.endPoint = self.brush?.startPoint
self.sendPoints.append((self.brush?.startPoint)!);
self.drawState = .began
// self.drawImage()
}
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
if self.brush != nil{
self.brush?.endPoint = touches.first?.location(in: self)
self.sendPoints.append((self.brush?.endPoint)!);
self.drawState = .moved
// self.drawImage()
}
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
if self.brush != nil{
self.brush?.endPoint = touches.first?.location(in: self)
self.sendPoints.append((self.brush?.endPoint)!);
self.drawState = .ended
// self.drawImage()
// 发送消息
self.drawOtherImage()
}
}
override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
if self.brush != nil{
self.drawState = .no
self.brush?.endPoint = nil
// 发送消息
self.drawOtherImage()
}
}
// 画自己的线
func drawImage(){
if(self.brush == nil){ return; }
UIGraphicsBeginImageContext(self.bounds.size)
let content = UIGraphicsGetCurrentContext()
UIColor.clear.setFill()
UIRectFill(self.bounds)
content?.setLineCap(.round)
content?.setLineWidth(self.strokeWidth)
content?.setStrokeColor(self.strokeColor.cgColor)
if let realImage = self.realImage{
realImage.draw(in: self.bounds)
}
brush?.strokeWidth = self.strokeWidth
brush?.drawInContext(content!)
content?.strokePath()
let previewImage = UIGraphicsGetImageFromCurrentImageContext()
self.realImage = previewImage
UIGraphicsEndImageContext()
self.image = previewImage
brush?.lastPoint = brush?.endPoint
}
// 画发过来的线
func drawOtherImage() {
if(self.brush == nil){ return; }
UIGraphicsBeginImageContext(self.bounds.size)
let content = UIGraphicsGetCurrentContext()
UIColor.clear.setFill()
UIRectFill(self.bounds)
content?.setLineCap(.round)
content?.setLineWidth(self.strokeWidth)
content?.setStrokeColor(self.strokeColor.cgColor)
if let realImage = self.realImage{
realImage.draw(in: self.bounds)
}
for (n,point) in self.sendPoints.enumerated(){
if(n == 0){
content?.move(to: point)
}else{
content?.addLine(to: point)
}
}
content?.strokePath()
let previewImage = UIGraphicsGetImageFromCurrentImageContext()
self.realImage = previewImage
UIGraphicsEndImageContext()
self.image = previewImage
self.sendPoints = []
}
}