8.22|8.22 Draw 画图板

【8.22|8.22 Draw 画图板】面向接口编程,多个类的共同点提出来,当做接口,充分利用多态的特性减少判断,利用封装,继承,能使得代码更加清晰易读,添加功能也不需要改太多东西。可扩展性高
将需要画的线,矩形,椭圆等都写成类

import UIKitclass ViewController: UIViewController {@IBAction func didClicked(sender: UIButton) { let cv = self.view as! CustomView //let array = cv.arraylet path = NSHomeDirectory() + "/Documents/1.jpg" // //NSKeyedArchiver.archiveRootObject(array, toFile: path)//1. 开始一个image上下文,绘制在内存的一个区域,保存为JPG UIGraphicsBeginImageContext(self.view.bounds.size) //2. 获取image context//a. //let context = UIGraphicsGetCurrentContext() // //for line in array { //line.draw(context!) //} // //CGContextDrawPath(context, .Stroke)//b. 将视图上的所有内容绘制到当前的context中 //截屏 cv.drawViewHierarchyInRect(cv.bounds, afterScreenUpdates: true)//3. 从当前上下文中获取图片(UIImage) let image = UIGraphicsGetImageFromCurrentImageContext() //let data = https://www.it610.com/article/UIImagePNGRepresentation(image) //UIImage -> NSData let data = https://www.it610.com/article/UIImageJPEGRepresentation(image, 0.4) try! data?.writeToFile(path, options: .AtomicWrite)//4. 结束图形上下文 UIGraphicsEndImageContext()//1. 可以自动转换 //Int/Float... <-> NSNumber //String <-> NSString //2. 容器的转换有条件,元素必须能够自动转换 //Dictionary <-> NSDictionary //Array <-> NSArray //var strArray = Array() //for point in array { ////CGPoint -> NSString //strArray.append(NSStringFromCGPoint(point)) //} ////NSArray是一个不可变类型 //(strArray as NSArray).writeToFile(path, atomically: true) }func changeShape(type: Shape.Type) { let cv = self.view as! CustomView cv.type = type }//meta programming //meta type: 元类型 @IBAction func didLineClicked(sender: UIButton) { changeShape(Line.self) }@IBAction func didRectClicked(sender: UIButton) { changeShape(Rectangle.self) }@IBAction func didCurveClicked(sender: UIButton) { changeShape(Curve.self) }@IBAction func didCircleClicked(sender: AnyObject) { changeShape(Circle.self) } @IBAction func RedColor(sender: UIButton) { let cv = self.view as! CustomView cv.color = UIColor.redColor().self }@IBAction func BlueColor(sender: UIButton) { let cv = self.view as! CustomView cv.color = UIColor.blueColor().self} override func viewDidLoad() { super.viewDidLoad()let cv = self.view as! CustomViewlet path = NSHomeDirectory() + "/Documents/array.plist" let array = NSKeyedUnarchiver.unarchiveObjectWithFile(path)if let a = array as? Array {cv.array = a }//let strArray = NSArray(contentsOfFile: path)! //for str in strArray { ////NSString -> CGPoint //let point = CGPointFromString(str as! String) //cv.array.append(point) //} }override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } }

import UIKitclass CustomView: UIView { var array = Array() var type: Shape.Type = Line.self //默认为Line类型 var color: UIColor? // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. //1. 视图显示 //2. 大小、位置改变 override func drawRect(rect: CGRect) { let context = UIGraphicsGetCurrentContext()for shape in array {CGContextSetLineWidth(context, 3) CGContextSaveGState(context)CGContextSetStrokeColorWithColor(context,shape.color?.CGColor) //多态 shape.draw(context!)CGContextStrokePath(context) }CGContextDrawPath(context, .Stroke) }func pointForTouches(touches: Set) -> CGPoint {let touch = touches.first! //UITouch let point = touch.locationInView(self)return point }override func touchesBegan(touches: Set, withEvent event: UIEvent?) { //获取起点 let point = pointForTouches(touches)let shape = type.init() //必须有required的构造函数 if color != nil { shape.color = color! } shape.addPoint(point) array.append(shape) }override func touchesMoved(touches: Set, withEvent event: UIEvent?) { //获取动态点 let point = pointForTouches(touches)let shape = array.last shape?.addPoint(point)self.setNeedsDisplay() //强制刷新(重绘) }override func touchesEnded(touches: Set, withEvent event: UIEvent?) { //获取终点 let point = pointForTouches(touches)let shape = array.last shape?.addPoint(point)self.setNeedsDisplay() //强制刷新(重绘) } }

import UIKit//enum ShapeType { //case Line //case Rect //case Ellipse //}//定义接口协议,方便其他类调用 protocol ShapeProtocol { func draw(context: CGContextRef) func addPoint(point: CGPoint) }class Shape: NSObject, NSCoding, ShapeProtocol {//var begin: CGPoint! //var end: CGPoint! //var cgcolor: CGColor!//NSArray中只能存放对象 var points = Array() var color:UIColor! required override init() { super.init()}required init?(coder aDecoder: NSCoder) { //begin = aDecoder.decodeCGPointForKey("begin") //end = aDecoder.decodeCGPointForKey("end")//取数据 if let array = aDecoder.decodeObjectForKey("points") as? Array { points = array } if let m = aDecoder.decodeObjectForKey("color") as?UIColor{ color = m } } //存数据 func encodeWithCoder(aCoder: NSCoder) { //aCoder.encodeCGPoint(begin, forKey: "begin") //aCoder.encodeCGPoint(end, forKey: "end")aCoder.encodeObject(points, forKey: "points") aCoder.encodeObject(color, forKey: "color")}func draw(context: CGContextRef) { }func addPoint(point: CGPoint) { } }

import UIKit //两个点之间的画图,如线,矩形,定义为SimpleShape简单图形类,继承Shape图形类 class SimpleShape: Shape { override func addPoint(point: CGPoint) { let p = Point(point: point)if points.count < 2 { points.append(p) } else { points[1] = p } } }

import UIKit //线 class Line: SimpleShape{ override func draw(context: CGContextRef) { //安全检查,如果少于两个点,就不画了 if points.count < 2 { return }CGContextMoveToPoint(context, points[0].x, points[0].y) CGContextAddLineToPoint(context, points[1].x, points[1].y) } }

import UIKit //矩形 class Rectangle: SimpleShape { override func draw(context: CGContextRef) { //安全检查,必须大于等于两个点才画 guard points.count >= 2 else { return }CGContextAddRect(context, CGRect(x: points[0].x, y: points[0].y, width: points[1].x - points[0].x, height: points[1].y - points[0].y)) } }---------------------------```bash import UIKit 任意线 class Curve: Shape { override func addPoint(point: CGPoint) { let p = Point(point: point)points.append(p) }override func draw(context: CGContextRef) { if points.count < 2 { return }CGContextMoveToPoint(context, points[0].x, points[0].y) for p in points { CGContextAddLineToPoint(context, p.x, p.y) } } }

import UIKit //椭圆 class Circle: SimpleShape { override func draw(context: CGContextRef) { let begin = points[0] //圆心 let end = points[1]//求半径 //r = ((x1-x0)**2 + (y1-y0)**2)^2 let radius = sqrt(pow((end.x - begin.x), 2) + pow((end.y - begin.y), 2))CGContextAddEllipseInRect(context, CGRect(x: begin.x - radius, y: begin.y - radius, width: radius + radius, height: radius + radius)) } }

import UIKitclass Point: NSObject, NSCoding { var x: CGFloat = 0 var y: CGFloat = 0init(point: CGPoint) { super.init()x = point.x y = point.y } //取数据 required init?(coder aDecoder: NSCoder) { x = CGFloat(aDecoder.decodeDoubleForKey("x")) y = CGFloat(aDecoder.decodeDoubleForKey("y")) } //存数据 func encodeWithCoder(aCoder: NSCoder) { aCoder.encodeDouble(Double(x), forKey: "x") aCoder.encodeDouble(Double(y), forKey: "y") } }

编译运行结果如下:
8.22|8.22 Draw 画图板
文章图片
Paste_Image.png 真彩色,类似取色工具 pod search colorpick
协议和扩展都要实现属性,实际上是计算属性 {set get}
为防止重构,写程序前要留后路

    推荐阅读