标签:之间 orm protoc 目标 tar 操作符 cte int add
写着玩儿的小程序,继续学习swift.运行效果+代码+知识点总结
class Canvas:UIView{ //负责线条的生成、操作与管理 let pathCreator:PathCreator //是否处于擦除状态 var isInErasering:Bool //橡皮擦视图 let eraserView:UIView override init(frame: CGRect) { isInErasering = false pathCreator = PathCreator() eraserView = UIView.init() eraserView.frame = CGRect(x: 0, y: 0, width: 10, height: 10) eraserView.backgroundColor = UIColor.white eraserView.alpha = 0 super.init(frame: frame) self.backgroundColor = UIColor.black self.addSubview(eraserView) let revokeBut = UIButton(type: UIButtonType.system) revokeBut.frame = CGRect(x: 20, y: 20, width: 80, height: 30) revokeBut.setTitle("撤销", for: UIControlState.normal) revokeBut.addTarget(self, action: #selector(revokeButClick), for: UIControlEvents.touchUpInside) self.addSubview(revokeBut) let cleanBut = UIButton(type: UIButtonType.system) cleanBut.frame = CGRect(x: 110, y: 20, width: 80, height: 30) cleanBut.setTitle("清空", for: UIControlState.normal) cleanBut.addTarget(self, action: #selector(cleanButClick), for: UIControlEvents.touchUpInside) self.addSubview(cleanBut) let eraserBut = UIButton(type: UIButtonType.system) eraserBut.frame = CGRect(x: 200, y: 20, width:80, height: 30) eraserBut.setTitle("橡皮", for: UIControlState.normal) eraserBut.setTitle("画笔", for: UIControlState.selected) eraserBut.addTarget(self, action: #selector(eraserButClick(but:)), for: UIControlEvents.touchUpInside) self.addSubview(eraserBut) let ges = UIPanGestureRecognizer(target: self, action:#selector(handleGes(ges:))) ges.maximumNumberOfTouches = 1 self.addGestureRecognizer(ges) } required public init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override public func layoutSubviews() { } @objc private func handleGes(ges:UIPanGestureRecognizer) -> Void { let point = ges.location(in: self) switch ges.state { case UIGestureRecognizerState.began: if isInErasering { //擦除状态,显示出橡皮擦 eraserView.alpha = 1 eraserView.center = point } //生成新的一笔 pathCreator.addNewPath(to: point,isEraser: isInErasering) self.setNeedsDisplay() case UIGestureRecognizerState.changed: if isInErasering { //移动橡皮擦 eraserView.center = ges.location(in: self) } //更新当前笔画路径 pathCreator.addLineForCurrentPath(to: point,isEraser:isInErasering) self.setNeedsDisplay() case UIGestureRecognizerState.ended: if isInErasering { //擦除状态,隐藏橡皮擦 eraserView.alpha = 0 eraserView.center = ges.location(in: self) } //更新当前笔画路径 pathCreator.addLineForCurrentPath(to: point,isEraser: isInErasering) self.setNeedsDisplay() case UIGestureRecognizerState.cancelled: print("cancel") case UIGestureRecognizerState.failed: print("fail") default: return } } override public func draw(_ rect: CGRect) { //画线 pathCreator.drawPaths() } @objc private func revokeButClick()->Void{ //撤销操作 pathCreator.revoke() self.setNeedsDisplay() } @objc private func cleanButClick()->Void{ //清空操作 pathCreator.clean() self.setNeedsDisplay() } @objc private func eraserButClick(but:UIButton)->Void{ //切换画图与擦除状态 if but.isSelected { but.isSelected = false isInErasering = false }else{ but.isSelected = true isInErasering = true } } }
PathCreator:具体线条绘制、管理
//每条子线段信息 struct BezierInfo{ let path:UIBezierPath//具体线段 let color:UIColor//线段对应颜色 init(path:UIBezierPath,color:UIColor){ self.path = path self.color = color } } class PathCreator{ //所有笔画 private var paths:[NSMutableArray]? //笔画内当前子线段 private var currentBezierPathInfo:BezierInfo? //当前笔画的所有子线段 private var currentPath:NSMutableArray? //当前笔画已经采集处理了几个触摸点 private var pointCountInOnePath = 0 static let colors = [UIColor.red,UIColor.orange,UIColor.yellow,UIColor.green,UIColor.blue,UIColor.gray,UIColor.purple] init() { paths = [] } //添加新笔画 func addNewPath(to:CGPoint,isEraser:Bool)->Void{ //创建起始线段 let path = UIBezierPath() path.lineWidth = 5 path.move(to: to) path.lineJoinStyle = CGLineJoin.round path.lineCapStyle = CGLineCap.round if !isEraser { //绑定线段与颜色信息 currentBezierPathInfo = BezierInfo(path: path, color: PathCreator.colors[0]) }else{ //处于擦除模式,颜色与画板背景色相同 currentBezierPathInfo = BezierInfo(path: path, color: UIColor.black) } //新建一个笔画 currentPath = NSMutableArray.init() //将起始线段加入当前笔画 currentPath!.add(currentBezierPathInfo) pointCountInOnePath = 0 //将当前笔画加入笔画数组 paths!.append(currentPath!) } //添加新的点,更新当前笔画路径 func addLineForCurrentPath(to:CGPoint,isEraser:Bool) -> Void { pointCountInOnePath += 1//同一笔画内,每7个点换一次颜色 if pointCountInOnePath % 7 == 0{//换颜色 if let currentBezierPathInfo = currentBezierPathInfo{ //将当前点加入当前子线段,更新当前子线段路径 currentBezierPathInfo.path.addLine(to: to) } //生成新的子线段 let path = UIBezierPath() path.lineWidth = 5 path.move(to: to) path.lineJoinStyle = CGLineJoin.round path.lineCapStyle = CGLineCap.round if !isEraser{ //给当前子线段设置下一个颜色 currentBezierPathInfo = BezierInfo(path: path, color: PathCreator.colors[currentPath!.count % 7]) }else{ //处于擦除模式,颜色与画板背景色相同 currentBezierPathInfo = BezierInfo(path: path, color: UIColor.black) } //将当前子线段加入当前笔画 currentPath!.add(currentBezierPathInfo) }else{ if let currentBezierPathInfo = currentBezierPathInfo{ //将当前点加入当前子线段,更新当前子线段路径 currentBezierPathInfo.path.addLine(to: to) } } } func drawPaths()->Void{ //画线 let pathCount = paths!.count for i in 0..<pathCount{ //取出所有笔画 let onePath = paths![i] let onePathCount = onePath.count for j in 0..<onePathCount{ //绘制每条笔画内每个子线段 let pathInfo = onePath.object(at: j) as! BezierInfo pathInfo.color.set() pathInfo.path.stroke() } } } func revoke()->Void{ //移走上一笔画 if paths!.count > 0 { paths!.removeLast() } } func clean()->Void{ //移走所有笔画 paths!.removeAll() } }
(纯)swift与oc采用了不同的运行机制,swift不再采用与oc一样的运行时(runtime)与消息分发机制,selector作为oc运行机制的产物,swift中也对其进行了保留与支持。
@objc修饰符的作用是将swift定义的类、方法等暴露给oc。
于是,下列selector中指定的方法,都要使用@objc进行修饰
cleanBut.addTarget(self, action: #selector(cleanButClick), for: UIControlEvents.touchUpInside)
let ges = UIPanGestureRecognizer(target: self, action:#selector(handleGes(ges:)))
@objc private func handleGes(ges:UIPanGestureRecognizer) -> Void
public init?(coder aDecoder: NSCoder)通过xcode找到该方法是在NSCoding协议中被定义的
public protocol NSCoding { public func encode(with aCoder: NSCoder) public init?(coder aDecoder: NSCoder) // NS_DESIGNATED_INITIALIZER }可以看到,此处并没有进行requird修饰,为什么还要求强制实现该构造方法呢?
let x:UInt16 = 100 let y:UInt8 = 10 //x + y会报错,不自动类型转换,更安全 let n = UInt8(x) + y上面例子中,当我们进行值类型之间的类型转换(UInt16->UInt8)时,其实借助的是UInt8的构造方法
/// Create an instance initialized to `value`. public init(integerLiteral value: UInt8)而当引用类型之间需要进行强制转换时,则需要借助as操作符
var people:People? let man:Man = Man() people = man print(people)//可选型变量 let beMan = people as! Man print (beMan)//强制转化后beMan不是可选型
var people:People? let man:Man = Man() people = man print(people)//可选型变量 let beMan = people as! Man? print (beMan)//强制转化后beMan为可选型转换后的结果类型完全由as!后面的目标类型决定,即便原对象在转换之前是可选型对象,但如果转换的目标类型不是可选型,则转换后得到的也就不是一个可选型了
Swift3.0学习实践-一个简单的画板(七色轨迹、可撤销、可清除、带橡皮擦)
标签:之间 orm protoc 目标 tar 操作符 cte int add
原文地址:http://blog.csdn.net/zhaochen_009/article/details/54908531